• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * @fileoverview Tests for kernel.js.
3 */
4goog.module('protobuf.runtime.KernelTest');
5
6goog.setTestOnly();
7
8const ByteString = goog.require('protobuf.ByteString');
9const Int64 = goog.require('protobuf.Int64');
10const InternalMessage = goog.require('protobuf.binary.InternalMessage');
11const Kernel = goog.require('protobuf.runtime.Kernel');
12const TestMessage = goog.require('protobuf.testing.binary.TestMessage');
13// Note to the reader:
14// Since the lazy accessor behavior changes with the checking level some of the
15// tests in this file have to know which checking level is enable to make
16// correct assertions.
17const {CHECK_BOUNDS, CHECK_CRITICAL_STATE, CHECK_CRITICAL_TYPE, CHECK_TYPE, MAX_FIELD_NUMBER} = goog.require('protobuf.internal.checks');
18
19/**
20 * @param {...number} bytes
21 * @return {!ArrayBuffer}
22 */
23function createArrayBuffer(...bytes) {
24  return new Uint8Array(bytes).buffer;
25}
26
27describe('Kernel', () => {
28  it('encodes none for the empty input', () => {
29    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
30    expect(accessor.serialize()).toEqual(new ArrayBuffer(0));
31  });
32
33  it('encodes and decodes max field number', () => {
34    const accessor = Kernel.fromArrayBuffer(
35        createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0x0F, 0x01));
36    expect(accessor.getBoolWithDefault(MAX_FIELD_NUMBER)).toBe(true);
37    accessor.setBool(MAX_FIELD_NUMBER, false);
38    expect(accessor.serialize())
39        .toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0x0F, 0x00));
40  });
41
42  it('uses the default pivot point', () => {
43    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
44    expect(accessor.getPivot()).toBe(24);
45  });
46
47  it('makes the pivot point configurable', () => {
48    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0), 50);
49    expect(accessor.getPivot()).toBe(50);
50  });
51});
52
53describe('Kernel hasFieldNumber', () => {
54  it('returns false for empty input', () => {
55    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
56    expect(accessor.hasFieldNumber(1)).toBe(false);
57  });
58
59  it('returns true for non-empty input', () => {
60    const bytes = createArrayBuffer(0x08, 0x01);
61    const accessor = Kernel.fromArrayBuffer(bytes);
62    expect(accessor.hasFieldNumber(1)).toBe(true);
63  });
64
65  it('returns false for empty array', () => {
66    const accessor = Kernel.createEmpty();
67    accessor.setPackedBoolIterable(1, []);
68    expect(accessor.hasFieldNumber(1)).toBe(false);
69  });
70
71  it('returns true for non-empty array', () => {
72    const accessor = Kernel.createEmpty();
73    accessor.setPackedBoolIterable(1, [true]);
74    expect(accessor.hasFieldNumber(1)).toBe(true);
75  });
76
77  it('updates value after write', () => {
78    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
79    expect(accessor.hasFieldNumber(1)).toBe(false);
80    accessor.setBool(1, false);
81    expect(accessor.hasFieldNumber(1)).toBe(true);
82  });
83});
84
85describe('Kernel clear field does', () => {
86  it('clear the field set', () => {
87    const accessor = Kernel.createEmpty();
88    accessor.setBool(1, true);
89    accessor.clearField(1);
90
91    expect(accessor.hasFieldNumber(1)).toEqual(false);
92    expect(accessor.serialize()).toEqual(new ArrayBuffer(0));
93    expect(accessor.getBoolWithDefault(1)).toEqual(false);
94  });
95
96  it('clear the field decoded', () => {
97    const bytes = createArrayBuffer(0x08, 0x01);
98    const accessor = Kernel.fromArrayBuffer(bytes);
99    accessor.clearField(1);
100
101    expect(accessor.hasFieldNumber(1)).toEqual(false);
102    expect(accessor.serialize()).toEqual(new ArrayBuffer(0));
103    expect(accessor.getBoolWithDefault(1)).toEqual(false);
104  });
105
106  it('clear the field read', () => {
107    const bytes = createArrayBuffer(0x08, 0x01);
108    const accessor = Kernel.fromArrayBuffer(bytes);
109    expect(accessor.getBoolWithDefault(1)).toEqual(true);
110    accessor.clearField(1);
111
112    expect(accessor.hasFieldNumber(1)).toEqual(false);
113    expect(accessor.serialize()).toEqual(new ArrayBuffer(0));
114    expect(accessor.getBoolWithDefault(1)).toEqual(false);
115  });
116
117  it('clear set and copied fields without affecting the old', () => {
118    const accessor = Kernel.createEmpty();
119    accessor.setBool(1, true);
120
121    const clonedAccessor = accessor.shallowCopy();
122    clonedAccessor.clearField(1);
123
124    expect(accessor.hasFieldNumber(1)).toEqual(true);
125    expect(accessor.getBoolWithDefault(1)).toEqual(true);
126    expect(clonedAccessor.hasFieldNumber(1)).toEqual(false);
127    expect(clonedAccessor.serialize()).toEqual(new ArrayBuffer(0));
128    expect(clonedAccessor.getBoolWithDefault(1)).toEqual(false);
129  });
130
131  it('clear decoded and copied fields without affecting the old', () => {
132    const bytes = createArrayBuffer(0x08, 0x01);
133    const accessor = Kernel.fromArrayBuffer(bytes);
134
135    const clonedAccessor = accessor.shallowCopy();
136    clonedAccessor.clearField(1);
137
138    expect(accessor.hasFieldNumber(1)).toEqual(true);
139    expect(accessor.getBoolWithDefault(1)).toEqual(true);
140    expect(clonedAccessor.hasFieldNumber(1)).toEqual(false);
141    expect(clonedAccessor.serialize()).toEqual(new ArrayBuffer(0));
142    expect(clonedAccessor.getBoolWithDefault(1)).toEqual(false);
143  });
144
145  it('clear read and copied fields without affecting the old', () => {
146    const bytes = createArrayBuffer(0x08, 0x01);
147    const accessor = Kernel.fromArrayBuffer(bytes);
148    expect(accessor.getBoolWithDefault(1)).toEqual(true);
149
150    const clonedAccessor = accessor.shallowCopy();
151    clonedAccessor.clearField(1);
152
153    expect(accessor.hasFieldNumber(1)).toEqual(true);
154    expect(accessor.getBoolWithDefault(1)).toEqual(true);
155    expect(clonedAccessor.hasFieldNumber(1)).toEqual(false);
156    expect(clonedAccessor.serialize()).toEqual(new ArrayBuffer(0));
157    expect(clonedAccessor.getBoolWithDefault(1)).toEqual(false);
158  });
159
160  it('clear the max field number', () => {
161    const accessor = Kernel.createEmpty();
162    accessor.setBool(MAX_FIELD_NUMBER, true);
163
164    accessor.clearField(MAX_FIELD_NUMBER);
165
166    expect(accessor.hasFieldNumber(MAX_FIELD_NUMBER)).toEqual(false);
167    expect(accessor.getBoolWithDefault(MAX_FIELD_NUMBER)).toEqual(false);
168  });
169});
170
171describe('Kernel shallow copy does', () => {
172  it('work for singular fields', () => {
173    const accessor = Kernel.createEmpty();
174    accessor.setBool(1, true);
175    accessor.setBool(MAX_FIELD_NUMBER, true);
176    const clonedAccessor = accessor.shallowCopy();
177    expect(clonedAccessor.getBoolWithDefault(1)).toEqual(true);
178    expect(clonedAccessor.getBoolWithDefault(MAX_FIELD_NUMBER)).toEqual(true);
179
180    accessor.setBool(1, false);
181    accessor.setBool(MAX_FIELD_NUMBER, false);
182    expect(clonedAccessor.getBoolWithDefault(1)).toEqual(true);
183    expect(clonedAccessor.getBoolWithDefault(MAX_FIELD_NUMBER)).toEqual(true);
184  });
185
186  it('work for repeated fields', () => {
187    const accessor = Kernel.createEmpty();
188
189    accessor.addUnpackedBoolIterable(2, [true, true]);
190
191    const clonedAccessor = accessor.shallowCopy();
192
193    // Modify a repeated field after clone
194    accessor.addUnpackedBoolElement(2, true);
195
196    const array = Array.from(clonedAccessor.getRepeatedBoolIterable(2));
197    expect(array).toEqual([true, true]);
198  });
199
200  it('work for repeated fields', () => {
201    const accessor = Kernel.createEmpty();
202
203    accessor.addUnpackedBoolIterable(2, [true, true]);
204
205    const clonedAccessor = accessor.shallowCopy();
206
207    // Modify a repeated field after clone
208    accessor.addUnpackedBoolElement(2, true);
209
210    const array = Array.from(clonedAccessor.getRepeatedBoolIterable(2));
211    expect(array).toEqual([true, true]);
212  });
213
214  it('return the correct bytes after serialization', () => {
215    const bytes = createArrayBuffer(0x08, 0x01, 0x10, 0x01);
216    const accessor = Kernel.fromArrayBuffer(bytes, /* pivot= */ 1);
217    const clonedAccessor = accessor.shallowCopy();
218
219    accessor.setBool(1, false);
220
221    expect(clonedAccessor.getBoolWithDefault(1)).toEqual(true);
222    expect(clonedAccessor.serialize()).toEqual(bytes);
223  });
224});
225
226describe('Kernel for singular boolean does', () => {
227  it('return false for the empty input', () => {
228    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
229    expect(accessor.getBoolWithDefault(
230               /* fieldNumber= */ 1))
231        .toBe(false);
232  });
233
234  it('return the value from the input', () => {
235    const bytes = createArrayBuffer(0x08, 0x01);
236    const accessor = Kernel.fromArrayBuffer(bytes);
237    expect(accessor.getBoolWithDefault(
238               /* fieldNumber= */ 1))
239        .toBe(true);
240  });
241
242  it('encode the value from the input', () => {
243    const bytes = createArrayBuffer(0x08, 0x01);
244    const accessor = Kernel.fromArrayBuffer(bytes);
245    expect(accessor.serialize()).toEqual(bytes);
246  });
247
248  it('encode the value from the input after read', () => {
249    const bytes = createArrayBuffer(0x08, 0x01);
250    const accessor = Kernel.fromArrayBuffer(bytes);
251    accessor.getBoolWithDefault(
252        /* fieldNumber= */ 1);
253    expect(accessor.serialize()).toEqual(bytes);
254  });
255
256  it('return the value from multiple inputs', () => {
257    const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x00);
258    const accessor = Kernel.fromArrayBuffer(bytes);
259    expect(accessor.getBoolWithDefault(
260               /* fieldNumber= */ 1))
261        .toBe(false);
262  });
263
264  it('encode the value from multiple inputs', () => {
265    const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x00);
266    const accessor = Kernel.fromArrayBuffer(bytes);
267    expect(accessor.serialize()).toEqual(bytes);
268  });
269
270  it('encode the value from multiple inputs after read', () => {
271    const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x00);
272    const accessor = Kernel.fromArrayBuffer(bytes);
273    accessor.getBoolWithDefault(/* fieldNumber= */ 1);
274    expect(accessor.serialize()).toEqual(bytes);
275  });
276
277  it('return the value from setter', () => {
278    const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x00);
279    const accessor = Kernel.fromArrayBuffer(bytes);
280    accessor.setBool(1, true);
281    expect(accessor.getBoolWithDefault(
282               /* fieldNumber= */ 1))
283        .toBe(true);
284  });
285
286  it('encode the value from setter', () => {
287    const bytes = createArrayBuffer(0x08, 0x01, 0x08, 0x00);
288    const accessor = Kernel.fromArrayBuffer(bytes);
289    const newBytes = createArrayBuffer(0x08, 0x01);
290    accessor.setBool(1, true);
291    expect(accessor.serialize()).toEqual(newBytes);
292  });
293
294  it('return the bool value from cache', () => {
295    const bytes = createArrayBuffer(0x08, 0x01);
296    const accessor = Kernel.fromArrayBuffer(bytes);
297    expect(accessor.getBoolWithDefault(
298               /* fieldNumber= */ 1))
299        .toBe(true);
300    // Make sure the value is cached.
301    bytes[1] = 0x00;
302    expect(accessor.getBoolWithDefault(
303               /* fieldNumber= */ 1))
304        .toBe(true);
305  });
306
307  it('fail when getting bool value with other wire types', () => {
308    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
309        0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
310    if (CHECK_CRITICAL_TYPE) {
311      expect(() => {
312        accessor.getBoolWithDefault(/* fieldNumber= */ 1);
313      }).toThrowError('Expected wire type: 0 but found: 1');
314    } else {
315      // Note in unchecked mode we produce invalid output for invalid inputs.
316      // This test just documents our behavior in those cases.
317      // These values might change at any point and are not considered
318      // what the implementation should be doing here.
319      expect(accessor.getBoolWithDefault(
320                 /* fieldNumber= */ 1))
321          .toBe(true);
322    }
323  });
324
325  it('fail when setting bool value with out-of-range field number', () => {
326    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
327    if (CHECK_TYPE) {
328      expect(() => accessor.setBool(MAX_FIELD_NUMBER + 1, false))
329          .toThrowError('Field number is out of range: 536870912');
330    } else {
331      // Note in unchecked mode we produce invalid output for invalid inputs.
332      // This test just documents our behavior in those cases.
333      // These values might change at any point and are not considered
334      // what the implementation should be doing here.
335      accessor.setBool(MAX_FIELD_NUMBER + 1, false);
336      expect(accessor.getBoolWithDefault(MAX_FIELD_NUMBER + 1)).toBe(false);
337    }
338  });
339
340  it('fail when setting bool value with number value', () => {
341    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
342    const fakeBoolean = /** @type {boolean} */ (/** @type {*} */ (2));
343    if (CHECK_CRITICAL_TYPE) {
344      expect(() => accessor.setBool(1, fakeBoolean))
345          .toThrowError('Must be a boolean, but got: 2');
346    } else {
347      // Note in unchecked mode we produce invalid output for invalid inputs.
348      // This test just documents our behavior in those cases.
349      // These values might change at any point and are not considered
350      // what the implementation should be doing here.
351      accessor.setBool(1, fakeBoolean);
352      expect(accessor.getBoolWithDefault(
353                 /* fieldNumber= */ 1))
354          .toBe(2);
355    }
356  });
357});
358
359describe('Kernel for singular message does', () => {
360  it('return message from the input', () => {
361    const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01);
362    const accessor = Kernel.fromArrayBuffer(bytes);
363    const msg = accessor.getMessageOrNull(1, TestMessage.instanceCreator);
364    expect(msg.getBoolWithDefault(1, false)).toBe(true);
365  });
366
367  it('return message from the input when pivot is set', () => {
368    const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01);
369    const accessor = Kernel.fromArrayBuffer(bytes, /* pivot= */ 0);
370    const msg = accessor.getMessageOrNull(1, TestMessage.instanceCreator);
371    expect(msg.getBoolWithDefault(1, false)).toBe(true);
372  });
373
374  it('encode message from the input', () => {
375    const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01);
376    const accessor = Kernel.fromArrayBuffer(bytes);
377    expect(accessor.serialize()).toEqual(bytes);
378  });
379
380  it('encode message from the input after read', () => {
381    const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01);
382    const accessor = Kernel.fromArrayBuffer(bytes);
383    accessor.getMessageOrNull(1, TestMessage.instanceCreator);
384    expect(accessor.serialize()).toEqual(bytes);
385  });
386
387  it('return message from multiple inputs', () => {
388    const bytes =
389        createArrayBuffer(0x0A, 0x02, 0x08, 0x01, 0x0A, 0x02, 0x10, 0x01);
390    const accessor = Kernel.fromArrayBuffer(bytes);
391    const msg = accessor.getMessageOrNull(1, TestMessage.instanceCreator);
392    expect(msg.getBoolWithDefault(1, false)).toBe(true);
393    expect(msg.getBoolWithDefault(2, false)).toBe(true);
394  });
395
396  it('encode message from multiple inputs', () => {
397    const bytes =
398        createArrayBuffer(0x0A, 0x02, 0x08, 0x01, 0x0A, 0x02, 0x10, 0x01);
399    const accessor = Kernel.fromArrayBuffer(bytes);
400    expect(accessor.serialize()).toEqual(bytes);
401  });
402
403  it('encode message merged from multiple inputs after read', () => {
404    const bytes =
405        createArrayBuffer(0x0A, 0x02, 0x08, 0x01, 0x0A, 0x02, 0x10, 0x01);
406    const expected = createArrayBuffer(0x0A, 0x04, 0x08, 0x01, 0x10, 0x01);
407    const accessor = Kernel.fromArrayBuffer(bytes);
408    accessor.getMessageOrNull(1, TestMessage.instanceCreator);
409    expect(accessor.serialize()).toEqual(expected);
410  });
411
412  it('return null for generic accessor', () => {
413    const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01);
414    const accessor = Kernel.fromArrayBuffer(bytes);
415    const accessor1 = accessor.getMessageAccessorOrNull(7);
416    expect(accessor1).toBe(null);
417  });
418
419  it('return null for generic accessor when pivot is set', () => {
420    const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01);
421    const accessor = Kernel.fromArrayBuffer(bytes);
422    const accessor1 = accessor.getMessageAccessorOrNull(7, /* pivot= */ 0);
423    expect(accessor1).toBe(null);
424  });
425
426  it('return generic accessor from the input', () => {
427    const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01);
428    const accessor = Kernel.fromArrayBuffer(bytes);
429    const accessor1 = accessor.getMessageAccessorOrNull(1);
430    expect(accessor1.getBoolWithDefault(1, false)).toBe(true);
431    // Second call returns a new instance, isn't cached.
432    const accessor2 = accessor.getMessageAccessorOrNull(1);
433    expect(accessor2.getBoolWithDefault(1, false)).toBe(true);
434    expect(accessor2).not.toBe(accessor1);
435  });
436
437  it('return generic accessor from the cached input', () => {
438    const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01);
439    const accessor = Kernel.fromArrayBuffer(bytes);
440    const wrappedMessage =
441        accessor.getMessageOrNull(1, TestMessage.instanceCreator);
442
443    // Returns accessor from the cached wrapper instance.
444    const accessor1 = accessor.getMessageAccessorOrNull(1);
445    expect(accessor1.getBoolWithDefault(1, false)).toBe(true);
446    expect(accessor1).toBe(
447        (/** @type {!InternalMessage} */ (wrappedMessage)).internalGetKernel());
448
449    // Second call returns exact same instance.
450    const accessor2 = accessor.getMessageAccessorOrNull(1);
451    expect(accessor2.getBoolWithDefault(1, false)).toBe(true);
452    expect(accessor2).toBe(
453        (/** @type {!InternalMessage} */ (wrappedMessage)).internalGetKernel());
454    expect(accessor2).toBe(accessor1);
455  });
456
457  it('return message from setter', () => {
458    const bytes = createArrayBuffer(0x08, 0x01);
459    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
460    const subaccessor = Kernel.fromArrayBuffer(bytes);
461    const submsg1 = new TestMessage(subaccessor);
462    accessor.setMessage(1, submsg1);
463    const submsg2 = accessor.getMessage(1, TestMessage.instanceCreator);
464    expect(submsg1).toBe(submsg2);
465  });
466
467  it('encode message from setter', () => {
468    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
469    const subaccessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
470    const subsubaccessor =
471        Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01));
472    const subsubmsg = new TestMessage(subsubaccessor);
473    subaccessor.setMessage(1, subsubmsg);
474    const submsg = new TestMessage(subaccessor);
475    accessor.setMessage(1, submsg);
476    const expected = createArrayBuffer(0x0A, 0x04, 0x0A, 0x02, 0x08, 0x01);
477    expect(accessor.serialize()).toEqual(expected);
478  });
479
480  it('encode message with multiple submessage from setter', () => {
481    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
482    const subaccessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
483    const subsubaccessor1 =
484        Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01));
485    const subsubaccessor2 =
486        Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x02));
487
488    const subsubmsg1 = new TestMessage(subsubaccessor1);
489    const subsubmsg2 = new TestMessage(subsubaccessor2);
490
491    subaccessor.setMessage(1, subsubmsg1);
492    subaccessor.setMessage(2, subsubmsg2);
493
494    const submsg = new TestMessage(subaccessor);
495    accessor.setMessage(1, submsg);
496
497    const expected = createArrayBuffer(
498        0x0A, 0x08, 0x0A, 0x02, 0x08, 0x01, 0x12, 0x02, 0x08, 0x02);
499    expect(accessor.serialize()).toEqual(expected);
500  });
501
502  it('leave hasFieldNumber unchanged after getMessageOrNull', () => {
503    const accessor = Kernel.createEmpty();
504    expect(accessor.hasFieldNumber(1)).toBe(false);
505    expect(accessor.getMessageOrNull(1, TestMessage.instanceCreator))
506        .toBe(null);
507    expect(accessor.hasFieldNumber(1)).toBe(false);
508  });
509
510  it('serialize changes to submessages made with getMessageOrNull', () => {
511    const intTwoBytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x02);
512    const accessor = Kernel.fromArrayBuffer(intTwoBytes);
513    const mutableSubMessage =
514        accessor.getMessageOrNull(1, TestMessage.instanceCreator);
515    mutableSubMessage.setInt32(1, 10);
516    const intTenBytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x0A);
517    expect(accessor.serialize()).toEqual(intTenBytes);
518  });
519
520  it('serialize additions to submessages made with getMessageOrNull', () => {
521    const intTwoBytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x02);
522    const accessor = Kernel.fromArrayBuffer(intTwoBytes);
523    const mutableSubMessage =
524        accessor.getMessageOrNull(1, TestMessage.instanceCreator);
525    mutableSubMessage.setInt32(2, 3);
526    // Sub message contains the original field, plus the new one.
527    expect(accessor.serialize())
528        .toEqual(createArrayBuffer(0x0A, 0x04, 0x08, 0x02, 0x10, 0x03));
529  });
530
531  it('fail with getMessageOrNull if immutable message exist in cache', () => {
532    const intTwoBytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x02);
533    const accessor = Kernel.fromArrayBuffer(intTwoBytes);
534
535    const readOnly = accessor.getMessage(1, TestMessage.instanceCreator);
536    if (CHECK_TYPE) {
537      expect(() => accessor.getMessageOrNull(1, TestMessage.instanceCreator))
538          .toThrow();
539    } else {
540      const mutableSubMessage =
541          accessor.getMessageOrNull(1, TestMessage.instanceCreator);
542      // The instance returned by getMessageOrNull is the exact same instance.
543      expect(mutableSubMessage).toBe(readOnly);
544
545      // Serializing the submessage does not write the changes
546      mutableSubMessage.setInt32(1, 0);
547      expect(accessor.serialize()).toEqual(intTwoBytes);
548    }
549  });
550
551  it('change hasFieldNumber after getMessageAttach', () => {
552    const accessor = Kernel.createEmpty();
553    expect(accessor.hasFieldNumber(1)).toBe(false);
554    expect(accessor.getMessageAttach(1, TestMessage.instanceCreator))
555        .not.toBe(null);
556    expect(accessor.hasFieldNumber(1)).toBe(true);
557  });
558
559  it('change hasFieldNumber after getMessageAttach when pivot is set', () => {
560    const accessor = Kernel.createEmpty();
561    expect(accessor.hasFieldNumber(1)).toBe(false);
562    expect(accessor.getMessageAttach(
563               1, TestMessage.instanceCreator, /* pivot= */ 1))
564        .not.toBe(null);
565    expect(accessor.hasFieldNumber(1)).toBe(true);
566  });
567
568  it('serialize submessages made with getMessageAttach', () => {
569    const accessor = Kernel.createEmpty();
570    const mutableSubMessage =
571        accessor.getMessageAttach(1, TestMessage.instanceCreator);
572    mutableSubMessage.setInt32(1, 10);
573    const intTenBytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x0A);
574    expect(accessor.serialize()).toEqual(intTenBytes);
575  });
576
577  it('serialize additions to submessages using getMessageAttach', () => {
578    const intTwoBytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x02);
579    const accessor = Kernel.fromArrayBuffer(intTwoBytes);
580    const mutableSubMessage =
581        accessor.getMessageAttach(1, TestMessage.instanceCreator);
582    mutableSubMessage.setInt32(2, 3);
583    // Sub message contains the original field, plus the new one.
584    expect(accessor.serialize())
585        .toEqual(createArrayBuffer(0x0A, 0x04, 0x08, 0x02, 0x10, 0x03));
586  });
587
588  it('fail with getMessageAttach if immutable message exist in cache', () => {
589    const intTwoBytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x02);
590    const accessor = Kernel.fromArrayBuffer(intTwoBytes);
591
592    const readOnly = accessor.getMessage(1, TestMessage.instanceCreator);
593    if (CHECK_TYPE) {
594      expect(() => accessor.getMessageAttach(1, TestMessage.instanceCreator))
595          .toThrow();
596    } else {
597      const mutableSubMessage =
598          accessor.getMessageAttach(1, TestMessage.instanceCreator);
599      // The instance returned by getMessageOrNull is the exact same instance.
600      expect(mutableSubMessage).toBe(readOnly);
601
602      // Serializing the submessage does not write the changes
603      mutableSubMessage.setInt32(1, 0);
604      expect(accessor.serialize()).toEqual(intTwoBytes);
605    }
606  });
607
608  it('read default message return empty message with getMessage', () => {
609    const bytes = new ArrayBuffer(0);
610    const accessor = Kernel.fromArrayBuffer(bytes);
611    expect(accessor.getMessage(1, TestMessage.instanceCreator)).toBeTruthy();
612    expect(accessor.getMessage(1, TestMessage.instanceCreator).serialize())
613        .toEqual(bytes);
614  });
615
616  it('read default message return null with getMessageOrNull', () => {
617    const bytes = new ArrayBuffer(0);
618    const accessor = Kernel.fromArrayBuffer(bytes);
619    expect(accessor.getMessageOrNull(1, TestMessage.instanceCreator))
620        .toBe(null);
621  });
622
623  it('read message preserve reference equality', () => {
624    const bytes = createArrayBuffer(0x0A, 0x02, 0x08, 0x01);
625    const accessor = Kernel.fromArrayBuffer(bytes);
626    const msg1 = accessor.getMessageOrNull(1, TestMessage.instanceCreator);
627    const msg2 = accessor.getMessageOrNull(1, TestMessage.instanceCreator);
628    const msg3 = accessor.getMessageAttach(1, TestMessage.instanceCreator);
629    expect(msg1).toBe(msg2);
630    expect(msg1).toBe(msg3);
631  });
632
633  it('fail when getting message with other wire types', () => {
634    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01));
635    expect(() => accessor.getMessageOrNull(1, TestMessage.instanceCreator))
636        .toThrow();
637  });
638
639  it('fail when submessage has incomplete data', () => {
640    const accessor =
641        Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x01, 0x08));
642    expect(() => accessor.getMessageOrNull(1, TestMessage.instanceCreator))
643        .toThrow();
644  });
645
646  it('fail when mutable submessage has incomplete data', () => {
647    const accessor =
648        Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x01, 0x08));
649    expect(() => accessor.getMessageAttach(1, TestMessage.instanceCreator))
650        .toThrow();
651  });
652
653  it('fail when getting message with null instance constructor', () => {
654    const accessor =
655        Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x02, 0x08, 0x01));
656    const nullMessage = /** @type {function(!Kernel):!TestMessage} */
657        (/** @type {*} */ (null));
658    expect(() => accessor.getMessageOrNull(1, nullMessage)).toThrow();
659  });
660
661  it('fail when setting message value with null value', () => {
662    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
663    const fakeMessage = /** @type {!TestMessage} */ (/** @type {*} */ (null));
664    if (CHECK_CRITICAL_TYPE) {
665      expect(() => accessor.setMessage(1, fakeMessage))
666          .toThrowError('Given value is not a message instance: null');
667    } else {
668      // Note in unchecked mode we produce invalid output for invalid inputs.
669      // This test just documents our behavior in those cases.
670      // These values might change at any point and are not considered
671      // what the implementation should be doing here.
672      accessor.setMessage(1, fakeMessage);
673      expect(accessor.getMessageOrNull(
674                 /* fieldNumber= */ 1, TestMessage.instanceCreator))
675          .toBeNull();
676    }
677  });
678});
679
680describe('Bytes access', () => {
681  const simpleByteString = ByteString.fromArrayBuffer(createArrayBuffer(1));
682
683  it('returns default value for empty input', () => {
684    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
685    expect(accessor.getBytesWithDefault(1)).toEqual(ByteString.EMPTY);
686  });
687
688  it('returns the default from parameter', () => {
689    const defaultByteString = ByteString.fromArrayBuffer(createArrayBuffer(1));
690    const returnValue = ByteString.fromArrayBuffer(createArrayBuffer(1));
691    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
692    expect(accessor.getBytesWithDefault(1, defaultByteString))
693        .toEqual(returnValue);
694  });
695
696  it('decodes value from wire', () => {
697    const accessor =
698        Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x01, 0x01));
699    expect(accessor.getBytesWithDefault(1)).toEqual(simpleByteString);
700  });
701
702  it('decodes value from wire with multple values being present', () => {
703    const accessor = Kernel.fromArrayBuffer(
704        createArrayBuffer(0x0A, 0x01, 0x00, 0x0A, 0x01, 0x01));
705    expect(accessor.getBytesWithDefault(1)).toEqual(simpleByteString);
706  });
707
708  it('fails when getting value with other wire types', () => {
709    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
710        0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01));
711    if (CHECK_CRITICAL_TYPE) {
712      expect(() => {
713        accessor.getBytesWithDefault(1);
714      }).toThrowError('Expected wire type: 2 but found: 1');
715    } else {
716      // Note in unchecked mode we produce invalid output for invalid inputs.
717      // This test just documents our behavior in those cases.
718      // These values might change at any point and are not considered
719      // what the implementation should be doing here.
720      const arrayBuffer = createArrayBuffer(1);
721      expect(accessor.getBytesWithDefault(1))
722          .toEqual(ByteString.fromArrayBuffer(arrayBuffer));
723    }
724  });
725
726  it('throws in getter for invalid fieldNumber', () => {
727    if (CHECK_BOUNDS) {
728      expect(
729          () => Kernel.createEmpty().getBytesWithDefault(-1, simpleByteString))
730          .toThrowError('Field number is out of range: -1');
731    } else {
732      expect(Kernel.createEmpty().getBytesWithDefault(-1, simpleByteString))
733          .toEqual(simpleByteString);
734    }
735  });
736
737  it('returns the value from setter', () => {
738    const bytes = createArrayBuffer(0x0A, 0x01, 0x00);
739    const accessor = Kernel.fromArrayBuffer(bytes);
740    accessor.setBytes(1, simpleByteString);
741    expect(accessor.getBytesWithDefault(1)).toEqual(simpleByteString);
742  });
743
744  it('encode the value from setter', () => {
745    const bytes = createArrayBuffer(0x0A, 0x01, 0x00);
746    const accessor = Kernel.fromArrayBuffer(bytes);
747    const newBytes = createArrayBuffer(0x0A, 0x01, 0x01);
748    accessor.setBytes(1, simpleByteString);
749    expect(accessor.serialize()).toEqual(newBytes);
750  });
751
752  it('returns value from cache', () => {
753    const bytes = createArrayBuffer(0x0A, 0x01, 0x01);
754    const accessor = Kernel.fromArrayBuffer(bytes);
755    expect(accessor.getBytesWithDefault(1)).toEqual(simpleByteString);
756    // Make sure the value is cached.
757    bytes[2] = 0x00;
758    expect(accessor.getBytesWithDefault(1)).toEqual(simpleByteString);
759  });
760
761  it('throws in setter for invalid fieldNumber', () => {
762    if (CHECK_BOUNDS) {
763      expect(() => Kernel.createEmpty().setBytes(-1, simpleByteString))
764          .toThrowError('Field number is out of range: -1');
765    } else {
766      const accessor = Kernel.createEmpty();
767      accessor.setBytes(-1, simpleByteString);
768      expect(accessor.getBytesWithDefault(-1)).toEqual(simpleByteString);
769    }
770  });
771
772  it('throws in setter for invalid value', () => {
773    if (CHECK_CRITICAL_TYPE) {
774      expect(
775          () => Kernel.createEmpty().setBytes(
776              1, /** @type {!ByteString} */ (/** @type {*} */ (null))))
777          .toThrow();
778    } else {
779      const accessor = Kernel.createEmpty();
780      accessor.setBytes(
781          1, /** @type {!ByteString} */ (/** @type {*} */ (null)));
782      expect(accessor.getBytesWithDefault(1)).toEqual(null);
783    }
784  });
785});
786
787describe('Fixed32 access', () => {
788  it('returns default value for empty input', () => {
789    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
790    expect(accessor.getFixed32WithDefault(1)).toEqual(0);
791  });
792
793  it('returns the default from parameter', () => {
794    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
795    expect(accessor.getFixed32WithDefault(1, 2)).toEqual(2);
796  });
797
798  it('decodes value from wire', () => {
799    const accessor =
800        Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x01, 0x00, 0x00, 0x00));
801    expect(accessor.getFixed32WithDefault(1)).toEqual(1);
802  });
803
804  it('decodes value from wire with multple values being present', () => {
805    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
806        0x0D, 0x01, 0x00, 0x80, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00));
807    expect(accessor.getFixed32WithDefault(1)).toEqual(2);
808  });
809
810  it('fails when getting value with other wire types', () => {
811    const accessor =
812        Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x80, 0x80, 0x80, 0x00));
813    if (CHECK_CRITICAL_TYPE) {
814      expect(() => {
815        accessor.getFixed32WithDefault(1);
816      }).toThrowError('Expected wire type: 5 but found: 0');
817    } else {
818      // Note in unchecked mode we produce invalid output for invalid inputs.
819      // This test just documents our behavior in those cases.
820      // These values might change at any point and are not considered
821      // what the implementation should be doing here.
822      expect(accessor.getFixed32WithDefault(1)).toEqual(8421504);
823    }
824  });
825
826  it('throws in getter for invalid fieldNumber', () => {
827    if (CHECK_BOUNDS) {
828      expect(() => Kernel.createEmpty().getFixed32WithDefault(-1, 1))
829          .toThrowError('Field number is out of range: -1');
830    } else {
831      expect(Kernel.createEmpty().getFixed32WithDefault(-1, 1)).toEqual(1);
832    }
833  });
834
835  it('returns the value from setter', () => {
836    const bytes = createArrayBuffer(0x0D, 0x01, 0x00, 0x00, 0x00);
837    const accessor = Kernel.fromArrayBuffer(bytes);
838    accessor.setFixed32(1, 2);
839    expect(accessor.getFixed32WithDefault(1)).toEqual(2);
840  });
841
842  it('encode the value from setter', () => {
843    const bytes = createArrayBuffer(0x0D, 0x01, 0x00, 0x00, 0x00);
844    const accessor = Kernel.fromArrayBuffer(bytes);
845    const newBytes = createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00);
846    accessor.setFixed32(1, 0);
847    expect(accessor.serialize()).toEqual(newBytes);
848  });
849
850  it('returns value from cache', () => {
851    const bytes = createArrayBuffer(0x0D, 0x01, 0x00, 0x00, 0x00);
852    const accessor = Kernel.fromArrayBuffer(bytes);
853    expect(accessor.getFixed32WithDefault(1)).toBe(1);
854    // Make sure the value is cached.
855    bytes[2] = 0x00;
856    expect(accessor.getFixed32WithDefault(1)).toBe(1);
857  });
858
859  it('throws in setter for invalid fieldNumber', () => {
860    if (CHECK_BOUNDS) {
861      expect(() => Kernel.createEmpty().setFixed32(-1, 1))
862          .toThrowError('Field number is out of range: -1');
863    } else {
864      const accessor = Kernel.createEmpty();
865      accessor.setFixed32(-1, 1);
866      expect(accessor.getFixed32WithDefault(-1)).toEqual(1);
867    }
868  });
869
870  it('throws in setter for invalid value', () => {
871    if (CHECK_CRITICAL_TYPE) {
872      expect(
873          () => Kernel.createEmpty().setFixed32(
874              1, /** @type {number} */ (/** @type {*} */ (null))))
875          .toThrow();
876    } else {
877      const accessor = Kernel.createEmpty();
878      accessor.setFixed32(1, /** @type {number} */ (/** @type {*} */ (null)));
879      expect(accessor.getFixed32WithDefault(1)).toEqual(null);
880    }
881  });
882
883  it('throws in setter for negative value', () => {
884    if (CHECK_CRITICAL_TYPE) {
885      expect(() => Kernel.createEmpty().setFixed32(1, -1)).toThrow();
886    } else {
887      const accessor = Kernel.createEmpty();
888      accessor.setFixed32(1, -1);
889      expect(accessor.getFixed32WithDefault(1)).toEqual(-1);
890    }
891  });
892});
893
894describe('Fixed64 access', () => {
895  it('returns default value for empty input', () => {
896    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
897    expect(accessor.getFixed64WithDefault(1)).toEqual(Int64.fromInt(0));
898  });
899
900  it('returns the default from parameter', () => {
901    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
902    expect(accessor.getFixed64WithDefault(1, Int64.fromInt(2)))
903        .toEqual(Int64.fromInt(2));
904  });
905
906  it('decodes value from wire', () => {
907    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
908        0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
909    expect(accessor.getFixed64WithDefault(1)).toEqual(Int64.fromInt(1));
910  });
911
912  it('decodes value from wire with multple values being present', () => {
913    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
914        0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x00,
915        0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
916    expect(accessor.getFixed64WithDefault(1)).toEqual(Int64.fromInt(2));
917  });
918
919  if (CHECK_CRITICAL_STATE) {
920    it('fails when getting value with other wire types', () => {
921      const accessor = Kernel.fromArrayBuffer(
922          createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00));
923      expect(() => {
924        accessor.getFixed64WithDefault(1);
925      }).toThrow();
926    });
927  }
928
929  it('throws in getter for invalid fieldNumber', () => {
930    if (CHECK_BOUNDS) {
931      expect(
932          () =>
933              Kernel.createEmpty().getFixed64WithDefault(-1, Int64.fromInt(1)))
934          .toThrowError('Field number is out of range: -1');
935    } else {
936      expect(Kernel.createEmpty().getFixed64WithDefault(-1, Int64.fromInt(1)))
937          .toEqual(Int64.fromInt(1));
938    }
939  });
940
941  it('returns the value from setter', () => {
942    const bytes =
943        createArrayBuffer(0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
944    const accessor = Kernel.fromArrayBuffer(bytes);
945    accessor.setFixed64(1, Int64.fromInt(2));
946    expect(accessor.getFixed64WithDefault(1)).toEqual(Int64.fromInt(2));
947  });
948
949  it('encode the value from setter', () => {
950    const bytes =
951        createArrayBuffer(0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
952    const accessor = Kernel.fromArrayBuffer(bytes);
953    const newBytes =
954        createArrayBuffer(0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
955    accessor.setFixed64(1, Int64.fromInt(0));
956    expect(accessor.serialize()).toEqual(newBytes);
957  });
958
959  it('returns value from cache', () => {
960    const bytes =
961        createArrayBuffer(0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
962    const accessor = Kernel.fromArrayBuffer(bytes);
963    expect(accessor.getFixed64WithDefault(1)).toEqual(Int64.fromInt(1));
964    // Make sure the value is cached.
965    bytes[2] = 0x00;
966    expect(accessor.getFixed64WithDefault(1)).toEqual(Int64.fromInt(1));
967  });
968
969  it('throws in setter for invalid fieldNumber', () => {
970    if (CHECK_BOUNDS) {
971      expect(() => Kernel.createEmpty().setFixed64(-1, Int64.fromInt(1)))
972          .toThrowError('Field number is out of range: -1');
973    } else {
974      const accessor = Kernel.createEmpty();
975      accessor.setFixed64(-1, Int64.fromInt(1));
976      expect(accessor.getFixed64WithDefault(-1)).toEqual(Int64.fromInt(1));
977    }
978  });
979
980  it('throws in setter for invalid value', () => {
981    if (CHECK_CRITICAL_TYPE) {
982      expect(
983          () => Kernel.createEmpty().setSfixed64(
984              1, /** @type {!Int64} */ (/** @type {*} */ (null))))
985          .toThrow();
986    } else {
987      const accessor = Kernel.createEmpty();
988      accessor.setFixed64(1, /** @type {!Int64} */ (/** @type {*} */ (null)));
989      expect(accessor.getFixed64WithDefault(1)).toEqual(null);
990    }
991  });
992});
993
994describe('Float access', () => {
995  it('returns default value for empty input', () => {
996    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
997    expect(accessor.getFloatWithDefault(1)).toEqual(0);
998  });
999
1000  it('returns the default from parameter', () => {
1001    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1002    expect(accessor.getFloatWithDefault(1, 2)).toEqual(2);
1003  });
1004
1005  it('decodes value from wire', () => {
1006    const accessor =
1007        Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x80, 0x3F));
1008    expect(accessor.getFloatWithDefault(1)).toEqual(1);
1009  });
1010
1011  it('decodes value from wire with multple values being present', () => {
1012    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
1013        0x0D, 0x00, 0x00, 0x80, 0x3F, 0x0D, 0x00, 0x00, 0x80, 0xBF));
1014    expect(accessor.getFloatWithDefault(1)).toEqual(-1);
1015  });
1016
1017  if (CHECK_CRITICAL_STATE) {
1018    it('fails when getting float value with other wire types', () => {
1019      const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
1020          0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F));
1021      expect(() => {
1022        accessor.getFloatWithDefault(1);
1023      }).toThrow();
1024    });
1025  }
1026
1027
1028  it('throws in getter for invalid fieldNumber', () => {
1029    if (CHECK_BOUNDS) {
1030      expect(() => Kernel.createEmpty().getFloatWithDefault(-1, 1))
1031          .toThrowError('Field number is out of range: -1');
1032    } else {
1033      expect(Kernel.createEmpty().getFloatWithDefault(-1, 1)).toEqual(1);
1034    }
1035  });
1036
1037  it('returns the value from setter', () => {
1038    const bytes = createArrayBuffer(0x0D, 0x00, 0x00, 0x80, 0x3F);
1039    const accessor = Kernel.fromArrayBuffer(bytes);
1040    accessor.setFloat(1, 1.6);
1041    expect(accessor.getFloatWithDefault(1)).toEqual(Math.fround(1.6));
1042  });
1043
1044  it('encode the value from setter', () => {
1045    const bytes = createArrayBuffer(0x0D, 0x00, 0x00, 0x80, 0x3F);
1046    const accessor = Kernel.fromArrayBuffer(bytes);
1047    const newBytes = createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00);
1048    accessor.setFloat(1, 0);
1049    expect(accessor.serialize()).toEqual(newBytes);
1050  });
1051
1052  it('returns float value from cache', () => {
1053    const bytes = createArrayBuffer(0x0D, 0x00, 0x00, 0x80, 0x3F);
1054    const accessor = Kernel.fromArrayBuffer(bytes);
1055    expect(accessor.getFloatWithDefault(1)).toBe(1);
1056    // Make sure the value is cached.
1057    bytes[2] = 0x00;
1058    expect(accessor.getFloatWithDefault(1)).toBe(1);
1059  });
1060
1061  it('throws in setter for invalid fieldNumber', () => {
1062    if (CHECK_BOUNDS) {
1063      expect(() => Kernel.createEmpty().setFloat(-1, 1))
1064          .toThrowError('Field number is out of range: -1');
1065    } else {
1066      const accessor = Kernel.createEmpty();
1067      accessor.setFloat(-1, 1);
1068      expect(accessor.getFloatWithDefault(-1)).toEqual(1);
1069    }
1070  });
1071
1072  it('throws in setter for invalid value', () => {
1073    if (CHECK_CRITICAL_TYPE) {
1074      expect(
1075          () => Kernel.createEmpty().setFloat(
1076              1, /** @type {number} */ (/** @type {*} */ (null))))
1077          .toThrow();
1078    } else {
1079      const accessor = Kernel.createEmpty();
1080      accessor.setFloat(1, /** @type {number} */ (/** @type {*} */ (null)));
1081      expect(accessor.getFloatWithDefault(1)).toEqual(0);
1082    }
1083  });
1084
1085  it('throws in setter for value outside of float32 precision', () => {
1086    if (CHECK_CRITICAL_TYPE) {
1087      expect(() => Kernel.createEmpty().setFloat(1, Number.MAX_VALUE))
1088          .toThrow();
1089    } else {
1090      const accessor = Kernel.createEmpty();
1091      accessor.setFloat(1, Number.MAX_VALUE);
1092      expect(accessor.getFloatWithDefault(1)).toEqual(Infinity);
1093    }
1094  });
1095});
1096
1097describe('Int32 access', () => {
1098  it('returns default value for empty input', () => {
1099    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1100    expect(accessor.getInt32WithDefault(1)).toEqual(0);
1101  });
1102
1103  it('returns the default from parameter', () => {
1104    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1105    expect(accessor.getInt32WithDefault(1, 2)).toEqual(2);
1106  });
1107
1108  it('decodes value from wire', () => {
1109    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01));
1110    expect(accessor.getInt32WithDefault(1)).toEqual(1);
1111  });
1112
1113  it('decodes value from wire with multple values being present', () => {
1114    const accessor =
1115        Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02));
1116    expect(accessor.getInt32WithDefault(1)).toEqual(2);
1117  });
1118
1119  it('fails when getting value with other wire types', () => {
1120    const accessor =
1121        Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00));
1122    if (CHECK_CRITICAL_TYPE) {
1123      expect(() => {
1124        accessor.getInt32WithDefault(1);
1125      }).toThrowError('Expected wire type: 0 but found: 5');
1126    } else {
1127      // Note in unchecked mode we produce invalid output for invalid inputs.
1128      // This test just documents our behavior in those cases.
1129      // These values might change at any point and are not considered
1130      // what the implementation should be doing here.
1131      expect(accessor.getInt32WithDefault(1)).toEqual(0);
1132    }
1133  });
1134
1135  it('throws in getter for invalid fieldNumber', () => {
1136    if (CHECK_BOUNDS) {
1137      expect(() => Kernel.createEmpty().getInt32WithDefault(-1, 1))
1138          .toThrowError('Field number is out of range: -1');
1139    } else {
1140      expect(Kernel.createEmpty().getInt32WithDefault(-1, 1)).toEqual(1);
1141    }
1142  });
1143
1144  it('returns the value from setter', () => {
1145    const bytes = createArrayBuffer(0x08, 0x01);
1146    const accessor = Kernel.fromArrayBuffer(bytes);
1147    accessor.setInt32(1, 2);
1148    expect(accessor.getInt32WithDefault(1)).toEqual(2);
1149  });
1150
1151  it('encode the value from setter', () => {
1152    const bytes = createArrayBuffer(0x08, 0x01);
1153    const accessor = Kernel.fromArrayBuffer(bytes);
1154    const newBytes = createArrayBuffer(0x08, 0x00);
1155    accessor.setInt32(1, 0);
1156    expect(accessor.serialize()).toEqual(newBytes);
1157  });
1158
1159  it('returns value from cache', () => {
1160    const bytes = createArrayBuffer(0x08, 0x01);
1161    const accessor = Kernel.fromArrayBuffer(bytes);
1162    expect(accessor.getInt32WithDefault(1)).toBe(1);
1163    // Make sure the value is cached.
1164    bytes[2] = 0x00;
1165    expect(accessor.getInt32WithDefault(1)).toBe(1);
1166  });
1167
1168  it('throws in setter for invalid fieldNumber', () => {
1169    if (CHECK_BOUNDS) {
1170      expect(() => Kernel.createEmpty().setInt32(-1, 1))
1171          .toThrowError('Field number is out of range: -1');
1172    } else {
1173      const accessor = Kernel.createEmpty();
1174      accessor.setInt32(-1, 1);
1175      expect(accessor.getInt32WithDefault(-1)).toEqual(1);
1176    }
1177  });
1178
1179  it('throws in setter for invalid value', () => {
1180    if (CHECK_CRITICAL_TYPE) {
1181      expect(
1182          () => Kernel.createEmpty().setInt32(
1183              1, /** @type {number} */ (/** @type {*} */ (null))))
1184          .toThrow();
1185    } else {
1186      const accessor = Kernel.createEmpty();
1187      accessor.setInt32(1, /** @type {number} */ (/** @type {*} */ (null)));
1188      expect(accessor.getInt32WithDefault(1)).toEqual(null);
1189    }
1190  });
1191});
1192
1193describe('Int64 access', () => {
1194  it('returns default value for empty input', () => {
1195    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1196    expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(0));
1197  });
1198
1199  it('returns the default from parameter', () => {
1200    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1201    expect(accessor.getInt64WithDefault(1, Int64.fromInt(2)))
1202        .toEqual(Int64.fromInt(2));
1203  });
1204
1205  it('decodes value from wire', () => {
1206    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01));
1207    expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(1));
1208  });
1209
1210  it('decodes value from wire with multple values being present', () => {
1211    const accessor =
1212        Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02));
1213    expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(2));
1214  });
1215
1216  it('fails when getting value with other wire types', () => {
1217    const accessor =
1218        Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00));
1219    if (CHECK_CRITICAL_TYPE) {
1220      expect(() => {
1221        accessor.getInt64WithDefault(1);
1222      }).toThrowError('Expected wire type: 0 but found: 5');
1223    } else {
1224      // Note in unchecked mode we produce invalid output for invalid inputs.
1225      // This test just documents our behavior in those cases.
1226      // These values might change at any point and are not considered
1227      // what the implementation should be doing here.
1228      expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(0));
1229    }
1230  });
1231
1232  it('throws in getter for invalid fieldNumber', () => {
1233    if (CHECK_BOUNDS) {
1234      expect(
1235          () => Kernel.createEmpty().getInt64WithDefault(-1, Int64.fromInt(1)))
1236          .toThrowError('Field number is out of range: -1');
1237    } else {
1238      expect(Kernel.createEmpty().getInt64WithDefault(-1, Int64.fromInt(1)))
1239          .toEqual(Int64.fromInt(1));
1240    }
1241  });
1242
1243  it('returns the value from setter', () => {
1244    const bytes = createArrayBuffer(0x08, 0x01);
1245    const accessor = Kernel.fromArrayBuffer(bytes);
1246    accessor.setInt64(1, Int64.fromInt(2));
1247    expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(2));
1248  });
1249
1250  it('encode the value from setter', () => {
1251    const bytes = createArrayBuffer(0x08, 0x01);
1252    const accessor = Kernel.fromArrayBuffer(bytes);
1253    const newBytes = createArrayBuffer(0x08, 0x00);
1254    accessor.setInt64(1, Int64.fromInt(0));
1255    expect(accessor.serialize()).toEqual(newBytes);
1256  });
1257
1258  it('returns value from cache', () => {
1259    const bytes = createArrayBuffer(0x08, 0x01);
1260    const accessor = Kernel.fromArrayBuffer(bytes);
1261    expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(1));
1262    // Make sure the value is cached.
1263    bytes[2] = 0x00;
1264    expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(1));
1265  });
1266
1267  it('throws in setter for invalid fieldNumber', () => {
1268    if (CHECK_BOUNDS) {
1269      expect(() => Kernel.createEmpty().setInt64(-1, Int64.fromInt(1)))
1270          .toThrowError('Field number is out of range: -1');
1271    } else {
1272      const accessor = Kernel.createEmpty();
1273      accessor.setInt64(-1, Int64.fromInt(1));
1274      expect(accessor.getInt64WithDefault(-1)).toEqual(Int64.fromInt(1));
1275    }
1276  });
1277
1278  it('throws in setter for invalid value', () => {
1279    if (CHECK_CRITICAL_TYPE) {
1280      expect(
1281          () => Kernel.createEmpty().setInt64(
1282              1, /** @type {!Int64} */ (/** @type {*} */ (null))))
1283          .toThrow();
1284    } else {
1285      const accessor = Kernel.createEmpty();
1286      accessor.setInt64(1, /** @type {!Int64} */ (/** @type {*} */ (null)));
1287      expect(accessor.getInt64WithDefault(1)).toEqual(null);
1288    }
1289  });
1290});
1291
1292describe('Sfixed32 access', () => {
1293  it('returns default value for empty input', () => {
1294    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1295    expect(accessor.getSfixed32WithDefault(1)).toEqual(0);
1296  });
1297
1298  it('returns the default from parameter', () => {
1299    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1300    expect(accessor.getSfixed32WithDefault(1, 2)).toEqual(2);
1301  });
1302
1303  it('decodes value from wire', () => {
1304    const accessor =
1305        Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x01, 0x00, 0x00, 0x00));
1306    expect(accessor.getSfixed32WithDefault(1)).toEqual(1);
1307  });
1308
1309  it('decodes value from wire with multple values being present', () => {
1310    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
1311        0x0D, 0x01, 0x00, 0x80, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00));
1312    expect(accessor.getSfixed32WithDefault(1)).toEqual(2);
1313  });
1314
1315  it('fails when getting value with other wire types', () => {
1316    const accessor =
1317        Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x80, 0x80, 0x80, 0x00));
1318    if (CHECK_CRITICAL_TYPE) {
1319      expect(() => {
1320        accessor.getSfixed32WithDefault(1);
1321      }).toThrowError('Expected wire type: 5 but found: 0');
1322    } else {
1323      // Note in unchecked mode we produce invalid output for invalid inputs.
1324      // This test just documents our behavior in those cases.
1325      // These values might change at any point and are not considered
1326      // what the implementation should be doing here.
1327      expect(accessor.getSfixed32WithDefault(1)).toEqual(8421504);
1328    }
1329  });
1330
1331  it('throws in getter for invalid fieldNumber', () => {
1332    if (CHECK_BOUNDS) {
1333      expect(() => Kernel.createEmpty().getSfixed32WithDefault(-1, 1))
1334          .toThrowError('Field number is out of range: -1');
1335    } else {
1336      expect(Kernel.createEmpty().getSfixed32WithDefault(-1, 1)).toEqual(1);
1337    }
1338  });
1339
1340  it('returns the value from setter', () => {
1341    const bytes = createArrayBuffer(0x0D, 0x01, 0x00, 0x00, 0x00);
1342    const accessor = Kernel.fromArrayBuffer(bytes);
1343    accessor.setSfixed32(1, 2);
1344    expect(accessor.getSfixed32WithDefault(1)).toEqual(2);
1345  });
1346
1347  it('encode the value from setter', () => {
1348    const bytes = createArrayBuffer(0x0D, 0x01, 0x00, 0x00, 0x00);
1349    const accessor = Kernel.fromArrayBuffer(bytes);
1350    const newBytes = createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00);
1351    accessor.setSfixed32(1, 0);
1352    expect(accessor.serialize()).toEqual(newBytes);
1353  });
1354
1355  it('returns value from cache', () => {
1356    const bytes = createArrayBuffer(0x0D, 0x01, 0x00, 0x00, 0x00);
1357    const accessor = Kernel.fromArrayBuffer(bytes);
1358    expect(accessor.getSfixed32WithDefault(1)).toBe(1);
1359    // Make sure the value is cached.
1360    bytes[2] = 0x00;
1361    expect(accessor.getSfixed32WithDefault(1)).toBe(1);
1362  });
1363
1364  it('throws in setter for invalid fieldNumber', () => {
1365    if (CHECK_BOUNDS) {
1366      expect(() => Kernel.createEmpty().setSfixed32(-1, 1))
1367          .toThrowError('Field number is out of range: -1');
1368    } else {
1369      const accessor = Kernel.createEmpty();
1370      accessor.setSfixed32(-1, 1);
1371      expect(accessor.getSfixed32WithDefault(-1)).toEqual(1);
1372    }
1373  });
1374
1375  it('throws in setter for invalid value', () => {
1376    if (CHECK_CRITICAL_TYPE) {
1377      expect(
1378          () => Kernel.createEmpty().setSfixed32(
1379              1, /** @type {number} */ (/** @type {*} */ (null))))
1380          .toThrow();
1381    } else {
1382      const accessor = Kernel.createEmpty();
1383      accessor.setSfixed32(1, /** @type {number} */ (/** @type {*} */ (null)));
1384      expect(accessor.getSfixed32WithDefault(1)).toEqual(null);
1385    }
1386  });
1387});
1388
1389describe('Sfixed64 access', () => {
1390  it('returns default value for empty input', () => {
1391    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1392    expect(accessor.getSfixed64WithDefault(1)).toEqual(Int64.fromInt(0));
1393  });
1394
1395  it('returns the default from parameter', () => {
1396    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1397    expect(accessor.getSfixed64WithDefault(1, Int64.fromInt(2)))
1398        .toEqual(Int64.fromInt(2));
1399  });
1400
1401  it('decodes value from wire', () => {
1402    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
1403        0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
1404    expect(accessor.getSfixed64WithDefault(1)).toEqual(Int64.fromInt(1));
1405  });
1406
1407  it('decodes value from wire with multple values being present', () => {
1408    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
1409        0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x00,
1410        0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
1411    expect(accessor.getSfixed64WithDefault(1)).toEqual(Int64.fromInt(2));
1412  });
1413
1414  if (CHECK_CRITICAL_STATE) {
1415    it('fails when getting value with other wire types', () => {
1416      const accessor = Kernel.fromArrayBuffer(
1417          createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00));
1418      expect(() => {
1419        accessor.getSfixed64WithDefault(1);
1420      }).toThrow();
1421    });
1422  }
1423
1424  it('throws in getter for invalid fieldNumber', () => {
1425    if (CHECK_BOUNDS) {
1426      expect(
1427          () =>
1428              Kernel.createEmpty().getSfixed64WithDefault(-1, Int64.fromInt(1)))
1429          .toThrowError('Field number is out of range: -1');
1430    } else {
1431      expect(Kernel.createEmpty().getSfixed64WithDefault(-1, Int64.fromInt(1)))
1432          .toEqual(Int64.fromInt(1));
1433    }
1434  });
1435
1436  it('returns the value from setter', () => {
1437    const bytes =
1438        createArrayBuffer(0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
1439    const accessor = Kernel.fromArrayBuffer(bytes);
1440    accessor.setSfixed64(1, Int64.fromInt(2));
1441    expect(accessor.getSfixed64WithDefault(1)).toEqual(Int64.fromInt(2));
1442  });
1443
1444  it('encode the value from setter', () => {
1445    const bytes =
1446        createArrayBuffer(0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
1447    const accessor = Kernel.fromArrayBuffer(bytes);
1448    const newBytes =
1449        createArrayBuffer(0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
1450    accessor.setSfixed64(1, Int64.fromInt(0));
1451    expect(accessor.serialize()).toEqual(newBytes);
1452  });
1453
1454  it('returns value from cache', () => {
1455    const bytes =
1456        createArrayBuffer(0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
1457    const accessor = Kernel.fromArrayBuffer(bytes);
1458    expect(accessor.getSfixed64WithDefault(1)).toEqual(Int64.fromInt(1));
1459    // Make sure the value is cached.
1460    bytes[2] = 0x00;
1461    expect(accessor.getSfixed64WithDefault(1)).toEqual(Int64.fromInt(1));
1462  });
1463
1464  it('throws in setter for invalid fieldNumber', () => {
1465    if (CHECK_BOUNDS) {
1466      expect(() => Kernel.createEmpty().setSfixed64(-1, Int64.fromInt(1)))
1467          .toThrowError('Field number is out of range: -1');
1468    } else {
1469      const accessor = Kernel.createEmpty();
1470      accessor.setSfixed64(-1, Int64.fromInt(1));
1471      expect(accessor.getSfixed64WithDefault(-1)).toEqual(Int64.fromInt(1));
1472    }
1473  });
1474
1475  it('throws in setter for invalid value', () => {
1476    if (CHECK_CRITICAL_TYPE) {
1477      expect(
1478          () => Kernel.createEmpty().setSfixed64(
1479              1, /** @type {!Int64} */ (/** @type {*} */ (null))))
1480          .toThrow();
1481    } else {
1482      const accessor = Kernel.createEmpty();
1483      accessor.setSfixed64(1, /** @type {!Int64} */ (/** @type {*} */ (null)));
1484      expect(accessor.getSfixed64WithDefault(1)).toEqual(null);
1485    }
1486  });
1487});
1488
1489describe('Sint32 access', () => {
1490  it('returns default value for empty input', () => {
1491    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1492    expect(accessor.getSint32WithDefault(1)).toEqual(0);
1493  });
1494
1495  it('returns the default from parameter', () => {
1496    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1497    expect(accessor.getSint32WithDefault(1, 2)).toEqual(2);
1498  });
1499
1500  it('decodes value from wire', () => {
1501    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x02));
1502    expect(accessor.getSint32WithDefault(1)).toEqual(1);
1503  });
1504
1505  it('decodes value from wire with multple values being present', () => {
1506    const accessor =
1507        Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x03, 0x08, 0x02));
1508    expect(accessor.getSint32WithDefault(1)).toEqual(1);
1509  });
1510
1511  it('fails when getting value with other wire types', () => {
1512    const accessor =
1513        Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00));
1514    if (CHECK_CRITICAL_TYPE) {
1515      expect(() => {
1516        accessor.getSint32WithDefault(1);
1517      }).toThrowError('Expected wire type: 0 but found: 5');
1518    } else {
1519      // Note in unchecked mode we produce invalid output for invalid inputs.
1520      // This test just documents our behavior in those cases.
1521      // These values might change at any point and are not considered
1522      // what the implementation should be doing here.
1523      expect(accessor.getSint32WithDefault(1)).toEqual(0);
1524    }
1525  });
1526
1527  it('throws in getter for invalid fieldNumber', () => {
1528    if (CHECK_BOUNDS) {
1529      expect(() => Kernel.createEmpty().getSint32WithDefault(-1, 1))
1530          .toThrowError('Field number is out of range: -1');
1531    } else {
1532      expect(Kernel.createEmpty().getSint32WithDefault(-1, 1)).toEqual(1);
1533    }
1534  });
1535
1536  it('returns the value from setter', () => {
1537    const bytes = createArrayBuffer(0x08, 0x01);
1538    const accessor = Kernel.fromArrayBuffer(bytes);
1539    accessor.setSint32(1, 2);
1540    expect(accessor.getSint32WithDefault(1)).toEqual(2);
1541  });
1542
1543  it('encode the value from setter', () => {
1544    const bytes = createArrayBuffer(0x08, 0x01);
1545    const accessor = Kernel.fromArrayBuffer(bytes);
1546    const newBytes = createArrayBuffer(0x08, 0x00);
1547    accessor.setSint32(1, 0);
1548    expect(accessor.serialize()).toEqual(newBytes);
1549  });
1550
1551  it('returns value from cache', () => {
1552    const bytes = createArrayBuffer(0x08, 0x02);
1553    const accessor = Kernel.fromArrayBuffer(bytes);
1554    expect(accessor.getSint32WithDefault(1)).toBe(1);
1555    // Make sure the value is cached.
1556    bytes[2] = 0x00;
1557    expect(accessor.getSint32WithDefault(1)).toBe(1);
1558  });
1559
1560  it('throws in setter for invalid fieldNumber', () => {
1561    if (CHECK_BOUNDS) {
1562      expect(() => Kernel.createEmpty().setSint32(-1, 1))
1563          .toThrowError('Field number is out of range: -1');
1564    } else {
1565      const accessor = Kernel.createEmpty();
1566      accessor.setSint32(-1, 1);
1567      expect(accessor.getSint32WithDefault(-1)).toEqual(1);
1568    }
1569  });
1570
1571  it('throws in setter for invalid value', () => {
1572    if (CHECK_CRITICAL_TYPE) {
1573      expect(
1574          () => Kernel.createEmpty().setSint32(
1575              1, /** @type {number} */ (/** @type {*} */ (null))))
1576          .toThrow();
1577    } else {
1578      const accessor = Kernel.createEmpty();
1579      accessor.setSint32(1, /** @type {number} */ (/** @type {*} */ (null)));
1580      expect(accessor.getSint32WithDefault(1)).toEqual(null);
1581    }
1582  });
1583});
1584
1585describe('SInt64 access', () => {
1586  it('returns default value for empty input', () => {
1587    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1588    expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(0));
1589  });
1590
1591  it('returns the default from parameter', () => {
1592    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1593    expect(accessor.getSint64WithDefault(1, Int64.fromInt(2)))
1594        .toEqual(Int64.fromInt(2));
1595  });
1596
1597  it('decodes value from wire', () => {
1598    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x02));
1599    expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(1));
1600  });
1601
1602  it('decodes value from wire with multple values being present', () => {
1603    const accessor =
1604        Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02));
1605    expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(1));
1606  });
1607
1608  it('fails when getting value with other wire types', () => {
1609    const accessor =
1610        Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00));
1611    if (CHECK_CRITICAL_TYPE) {
1612      expect(() => {
1613        accessor.getSint64WithDefault(1);
1614      }).toThrowError('Expected wire type: 0 but found: 5');
1615    } else {
1616      // Note in unchecked mode we produce invalid output for invalid inputs.
1617      // This test just documents our behavior in those cases.
1618      // These values might change at any point and are not considered
1619      // what the implementation should be doing here.
1620      expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(0));
1621    }
1622  });
1623
1624  it('throws in getter for invalid fieldNumber', () => {
1625    if (CHECK_BOUNDS) {
1626      expect(
1627          () => Kernel.createEmpty().getSint64WithDefault(-1, Int64.fromInt(1)))
1628          .toThrowError('Field number is out of range: -1');
1629    } else {
1630      expect(Kernel.createEmpty().getSint64WithDefault(-1, Int64.fromInt(1)))
1631          .toEqual(Int64.fromInt(1));
1632    }
1633  });
1634
1635  it('returns the value from setter', () => {
1636    const bytes = createArrayBuffer(0x08, 0x01);
1637    const accessor = Kernel.fromArrayBuffer(bytes);
1638    accessor.setSint64(1, Int64.fromInt(2));
1639    expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(2));
1640  });
1641
1642  it('encode the value from setter', () => {
1643    const bytes = createArrayBuffer(0x08, 0x01);
1644    const accessor = Kernel.fromArrayBuffer(bytes);
1645    const newBytes = createArrayBuffer(0x08, 0x00);
1646    accessor.setSint64(1, Int64.fromInt(0));
1647    expect(accessor.serialize()).toEqual(newBytes);
1648  });
1649
1650  it('returns value from cache', () => {
1651    const bytes = createArrayBuffer(0x08, 0x02);
1652    const accessor = Kernel.fromArrayBuffer(bytes);
1653    expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(1));
1654    // Make sure the value is cached.
1655    bytes[1] = 0x00;
1656    expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(1));
1657  });
1658
1659  it('throws in setter for invalid fieldNumber', () => {
1660    if (CHECK_BOUNDS) {
1661      expect(() => Kernel.createEmpty().setSint64(-1, Int64.fromInt(1)))
1662          .toThrowError('Field number is out of range: -1');
1663    } else {
1664      const accessor = Kernel.createEmpty();
1665      accessor.setInt64(-1, Int64.fromInt(1));
1666      expect(accessor.getSint64WithDefault(-1)).toEqual(Int64.fromInt(1));
1667    }
1668  });
1669
1670  it('throws in setter for invalid value', () => {
1671    if (CHECK_CRITICAL_TYPE) {
1672      expect(
1673          () => Kernel.createEmpty().setSint64(
1674              1, /** @type {!Int64} */ (/** @type {*} */ (null))))
1675          .toThrow();
1676    } else {
1677      const accessor = Kernel.createEmpty();
1678      accessor.setSint64(1, /** @type {!Int64} */ (/** @type {*} */ (null)));
1679      expect(accessor.getSint64WithDefault(1)).toEqual(null);
1680    }
1681  });
1682});
1683
1684describe('String access', () => {
1685  it('returns empty string for the empty input', () => {
1686    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1687    expect(accessor.getStringWithDefault(1)).toEqual('');
1688  });
1689
1690  it('returns the default for the empty input', () => {
1691    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1692    expect(accessor.getStringWithDefault(1, 'bar')).toEqual('bar');
1693  });
1694
1695  it('decodes value from wire', () => {
1696    const accessor =
1697        Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x01, 0x61));
1698    expect(accessor.getStringWithDefault(1)).toEqual('a');
1699  });
1700
1701  it('decodes value from wire with multple values being present', () => {
1702    const accessor = Kernel.fromArrayBuffer(
1703        createArrayBuffer(0x0A, 0x01, 0x60, 0x0A, 0x01, 0x61));
1704    expect(accessor.getStringWithDefault(1)).toEqual('a');
1705  });
1706
1707  if (CHECK_CRITICAL_STATE) {
1708    it('fails when getting string value with other wire types', () => {
1709      const accessor =
1710          Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x02, 0x08, 0x08));
1711      expect(() => {
1712        accessor.getStringWithDefault(1);
1713      }).toThrow();
1714    });
1715  }
1716
1717
1718  it('throws in getter for invalid fieldNumber', () => {
1719    if (CHECK_BOUNDS) {
1720      expect(() => Kernel.createEmpty().getStringWithDefault(-1, 'a'))
1721          .toThrowError('Field number is out of range: -1');
1722    } else {
1723      expect(Kernel.createEmpty().getStringWithDefault(-1, 'a')).toEqual('a');
1724    }
1725  });
1726
1727  it('returns the value from setter', () => {
1728    const bytes = createArrayBuffer(0x0A, 0x01, 0x61);
1729    const accessor = Kernel.fromArrayBuffer(bytes);
1730    accessor.setString(1, 'b');
1731    expect(accessor.getStringWithDefault(1)).toEqual('b');
1732  });
1733
1734  it('encode the value from setter', () => {
1735    const bytes = createArrayBuffer(0x0A, 0x01, 0x61);
1736    const accessor = Kernel.fromArrayBuffer(bytes);
1737    const newBytes = createArrayBuffer(0x0A, 0x01, 0x62);
1738    accessor.setString(1, 'b');
1739    expect(accessor.serialize()).toEqual(newBytes);
1740  });
1741
1742  it('returns string value from cache', () => {
1743    const bytes = createArrayBuffer(0x0A, 0x01, 0x61);
1744    const accessor = Kernel.fromArrayBuffer(bytes);
1745    expect(accessor.getStringWithDefault(1)).toBe('a');
1746    // Make sure the value is cached.
1747    bytes[2] = 0x00;
1748    expect(accessor.getStringWithDefault(1)).toBe('a');
1749  });
1750
1751  it('throws in setter for invalid fieldNumber', () => {
1752    if (CHECK_TYPE) {
1753      expect(() => Kernel.createEmpty().setString(-1, 'a'))
1754          .toThrowError('Field number is out of range: -1');
1755    } else {
1756      const accessor = Kernel.createEmpty();
1757      accessor.setString(-1, 'a');
1758      expect(accessor.getStringWithDefault(-1)).toEqual('a');
1759    }
1760  });
1761
1762  it('throws in setter for invalid value', () => {
1763    if (CHECK_CRITICAL_TYPE) {
1764      expect(
1765          () => Kernel.createEmpty().setString(
1766              1, /** @type {string} */ (/** @type {*} */ (null))))
1767          .toThrowError('Must be string, but got: null');
1768    } else {
1769      const accessor = Kernel.createEmpty();
1770      accessor.setString(1, /** @type {string} */ (/** @type {*} */ (null)));
1771      expect(accessor.getStringWithDefault(1)).toEqual(null);
1772    }
1773  });
1774});
1775
1776describe('Uint32 access', () => {
1777  it('returns default value for empty input', () => {
1778    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1779    expect(accessor.getUint32WithDefault(1)).toEqual(0);
1780  });
1781
1782  it('returns the default from parameter', () => {
1783    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1784    expect(accessor.getUint32WithDefault(1, 2)).toEqual(2);
1785  });
1786
1787  it('decodes value from wire', () => {
1788    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01));
1789    expect(accessor.getUint32WithDefault(1)).toEqual(1);
1790  });
1791
1792  it('decodes value from wire with multple values being present', () => {
1793    const accessor =
1794        Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02));
1795    expect(accessor.getUint32WithDefault(1)).toEqual(2);
1796  });
1797
1798  it('fails when getting value with other wire types', () => {
1799    const accessor =
1800        Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00));
1801    if (CHECK_CRITICAL_TYPE) {
1802      expect(() => {
1803        accessor.getUint32WithDefault(1);
1804      }).toThrowError('Expected wire type: 0 but found: 5');
1805    } else {
1806      // Note in unchecked mode we produce invalid output for invalid inputs.
1807      // This test just documents our behavior in those cases.
1808      // These values might change at any point and are not considered
1809      // what the implementation should be doing here.
1810      expect(accessor.getUint32WithDefault(1)).toEqual(0);
1811    }
1812  });
1813
1814  it('throws in getter for invalid fieldNumber', () => {
1815    if (CHECK_BOUNDS) {
1816      expect(() => Kernel.createEmpty().getUint32WithDefault(-1, 1))
1817          .toThrowError('Field number is out of range: -1');
1818    } else {
1819      expect(Kernel.createEmpty().getUint32WithDefault(-1, 1)).toEqual(1);
1820    }
1821  });
1822
1823  it('returns the value from setter', () => {
1824    const bytes = createArrayBuffer(0x08, 0x01);
1825    const accessor = Kernel.fromArrayBuffer(bytes);
1826    accessor.setUint32(1, 2);
1827    expect(accessor.getUint32WithDefault(1)).toEqual(2);
1828  });
1829
1830  it('encode the value from setter', () => {
1831    const bytes = createArrayBuffer(0x08, 0x01);
1832    const accessor = Kernel.fromArrayBuffer(bytes);
1833    const newBytes = createArrayBuffer(0x08, 0x00);
1834    accessor.setUint32(1, 0);
1835    expect(accessor.serialize()).toEqual(newBytes);
1836  });
1837
1838  it('returns value from cache', () => {
1839    const bytes = createArrayBuffer(0x08, 0x01);
1840    const accessor = Kernel.fromArrayBuffer(bytes);
1841    expect(accessor.getUint32WithDefault(1)).toBe(1);
1842    // Make sure the value is cached.
1843    bytes[2] = 0x00;
1844    expect(accessor.getUint32WithDefault(1)).toBe(1);
1845  });
1846
1847  it('throws in setter for invalid fieldNumber', () => {
1848    if (CHECK_BOUNDS) {
1849      expect(() => Kernel.createEmpty().setInt32(-1, 1))
1850          .toThrowError('Field number is out of range: -1');
1851    } else {
1852      const accessor = Kernel.createEmpty();
1853      accessor.setUint32(-1, 1);
1854      expect(accessor.getUint32WithDefault(-1)).toEqual(1);
1855    }
1856  });
1857
1858  it('throws in setter for invalid value', () => {
1859    if (CHECK_CRITICAL_TYPE) {
1860      expect(
1861          () => Kernel.createEmpty().setUint32(
1862              1, /** @type {number} */ (/** @type {*} */ (null))))
1863          .toThrow();
1864    } else {
1865      const accessor = Kernel.createEmpty();
1866      accessor.setUint32(1, /** @type {number} */ (/** @type {*} */ (null)));
1867      expect(accessor.getUint32WithDefault(1)).toEqual(null);
1868    }
1869  });
1870
1871  it('throws in setter for negative value', () => {
1872    if (CHECK_CRITICAL_TYPE) {
1873      expect(() => Kernel.createEmpty().setUint32(1, -1)).toThrow();
1874    } else {
1875      const accessor = Kernel.createEmpty();
1876      accessor.setUint32(1, -1);
1877      expect(accessor.getUint32WithDefault(1)).toEqual(-1);
1878    }
1879  });
1880});
1881
1882describe('Uint64 access', () => {
1883  it('returns default value for empty input', () => {
1884    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1885    expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(0));
1886  });
1887
1888  it('returns the default from parameter', () => {
1889    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1890    expect(accessor.getUint64WithDefault(1, Int64.fromInt(2)))
1891        .toEqual(Int64.fromInt(2));
1892  });
1893
1894  it('decodes value from wire', () => {
1895    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01));
1896    expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(1));
1897  });
1898
1899  it('decodes value from wire with multple values being present', () => {
1900    const accessor =
1901        Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02));
1902    expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(2));
1903  });
1904
1905  it('fails when getting value with other wire types', () => {
1906    const accessor =
1907        Kernel.fromArrayBuffer(createArrayBuffer(0x0D, 0x00, 0x00, 0x00, 0x00));
1908    if (CHECK_CRITICAL_TYPE) {
1909      expect(() => {
1910        accessor.getUint64WithDefault(1);
1911      }).toThrowError('Expected wire type: 0 but found: 5');
1912    } else {
1913      // Note in unchecked mode we produce invalid output for invalid inputs.
1914      // This test just documents our behavior in those cases.
1915      // These values might change at any point and are not considered
1916      // what the implementation should be doing here.
1917      expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(0));
1918    }
1919  });
1920
1921  it('throws in getter for invalid fieldNumber', () => {
1922    if (CHECK_BOUNDS) {
1923      expect(
1924          () => Kernel.createEmpty().getUint64WithDefault(-1, Int64.fromInt(1)))
1925          .toThrowError('Field number is out of range: -1');
1926    } else {
1927      expect(Kernel.createEmpty().getUint64WithDefault(-1, Int64.fromInt(1)))
1928          .toEqual(Int64.fromInt(1));
1929    }
1930  });
1931
1932  it('returns the value from setter', () => {
1933    const bytes = createArrayBuffer(0x08, 0x01);
1934    const accessor = Kernel.fromArrayBuffer(bytes);
1935    accessor.setUint64(1, Int64.fromInt(2));
1936    expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(2));
1937  });
1938
1939  it('encode the value from setter', () => {
1940    const bytes = createArrayBuffer(0x08, 0x01);
1941    const accessor = Kernel.fromArrayBuffer(bytes);
1942    const newBytes = createArrayBuffer(0x08, 0x00);
1943    accessor.setUint64(1, Int64.fromInt(0));
1944    expect(accessor.serialize()).toEqual(newBytes);
1945  });
1946
1947  it('returns value from cache', () => {
1948    const bytes = createArrayBuffer(0x08, 0x01);
1949    const accessor = Kernel.fromArrayBuffer(bytes);
1950    expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(1));
1951    // Make sure the value is cached.
1952    bytes[2] = 0x00;
1953    expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(1));
1954  });
1955
1956  it('throws in setter for invalid fieldNumber', () => {
1957    if (CHECK_BOUNDS) {
1958      expect(() => Kernel.createEmpty().setUint64(-1, Int64.fromInt(1)))
1959          .toThrowError('Field number is out of range: -1');
1960    } else {
1961      const accessor = Kernel.createEmpty();
1962      accessor.setUint64(-1, Int64.fromInt(1));
1963      expect(accessor.getUint64WithDefault(-1)).toEqual(Int64.fromInt(1));
1964    }
1965  });
1966
1967  it('throws in setter for invalid value', () => {
1968    if (CHECK_CRITICAL_TYPE) {
1969      expect(
1970          () => Kernel.createEmpty().setUint64(
1971              1, /** @type {!Int64} */ (/** @type {*} */ (null))))
1972          .toThrow();
1973    } else {
1974      const accessor = Kernel.createEmpty();
1975      accessor.setUint64(1, /** @type {!Int64} */ (/** @type {*} */ (null)));
1976      expect(accessor.getUint64WithDefault(1)).toEqual(null);
1977    }
1978  });
1979});
1980
1981describe('Double access', () => {
1982  it('returns default value for empty input', () => {
1983    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1984    expect(accessor.getDoubleWithDefault(1)).toEqual(0);
1985  });
1986
1987  it('returns the default from parameter', () => {
1988    const accessor = Kernel.fromArrayBuffer(createArrayBuffer());
1989    expect(accessor.getDoubleWithDefault(1, 2)).toEqual(2);
1990  });
1991
1992  it('decodes value from wire', () => {
1993    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
1994        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F));
1995    expect(accessor.getDoubleWithDefault(1)).toEqual(1);
1996  });
1997
1998
1999  it('decodes value from wire with multple values being present', () => {
2000    const accessor = Kernel.fromArrayBuffer(createArrayBuffer(
2001        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x09, 0x00, 0x00,
2002        0x00, 0x00, 0x00, 0x00, 0xF0, 0xBF));
2003    expect(accessor.getDoubleWithDefault(1)).toEqual(-1);
2004  });
2005
2006  if (CHECK_CRITICAL_STATE) {
2007    it('fails when getting double value with other wire types', () => {
2008      const accessor = Kernel.fromArrayBuffer(
2009          createArrayBuffer(0x0D, 0x00, 0x00, 0xF0, 0x3F));
2010      expect(() => {
2011        accessor.getDoubleWithDefault(1);
2012      }).toThrow();
2013    });
2014  }
2015
2016
2017  it('throws in getter for invalid fieldNumber', () => {
2018    if (CHECK_BOUNDS) {
2019      expect(() => Kernel.createEmpty().getDoubleWithDefault(-1, 1))
2020          .toThrowError('Field number is out of range: -1');
2021    } else {
2022      expect(Kernel.createEmpty().getDoubleWithDefault(-1, 1)).toEqual(1);
2023    }
2024  });
2025
2026  it('returns the value from setter', () => {
2027    const bytes =
2028        createArrayBuffer(0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F);
2029    const accessor = Kernel.fromArrayBuffer(bytes);
2030    accessor.setDouble(1, 2);
2031    expect(accessor.getDoubleWithDefault(1)).toEqual(2);
2032  });
2033
2034  it('encode the value from setter', () => {
2035    const bytes =
2036        createArrayBuffer(0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F);
2037    const accessor = Kernel.fromArrayBuffer(bytes);
2038    const newBytes =
2039        createArrayBuffer(0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
2040    accessor.setDouble(1, 0);
2041    expect(accessor.serialize()).toEqual(newBytes);
2042  });
2043
2044  it('returns string value from cache', () => {
2045    const bytes =
2046        createArrayBuffer(0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F);
2047    const accessor = Kernel.fromArrayBuffer(bytes);
2048    expect(accessor.getDoubleWithDefault(1)).toBe(1);
2049    // Make sure the value is cached.
2050    bytes[2] = 0x00;
2051    expect(accessor.getDoubleWithDefault(1)).toBe(1);
2052  });
2053
2054  it('throws in setter for invalid fieldNumber', () => {
2055    if (CHECK_BOUNDS) {
2056      expect(() => Kernel.createEmpty().setDouble(-1, 1))
2057          .toThrowError('Field number is out of range: -1');
2058    } else {
2059      const accessor = Kernel.createEmpty();
2060      accessor.setDouble(-1, 1);
2061      expect(accessor.getDoubleWithDefault(-1)).toEqual(1);
2062    }
2063  });
2064
2065  it('throws in setter for invalid value', () => {
2066    if (CHECK_CRITICAL_TYPE) {
2067      expect(
2068          () => Kernel.createEmpty().setDouble(
2069              1, /** @type {number} */ (/** @type {*} */ (null))))
2070          .toThrowError('Must be a number, but got: null');
2071    } else {
2072      const accessor = Kernel.createEmpty();
2073      accessor.setDouble(1, /** @type {number} */ (/** @type {*} */ (null)));
2074      expect(accessor.getDoubleWithDefault(1)).toEqual(null);
2075    }
2076  });
2077});
2078
2079describe('Kernel for singular group does', () => {
2080  it('return group from the input', () => {
2081    const bytes = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C);
2082    const accessor = Kernel.fromArrayBuffer(bytes);
2083    const msg = accessor.getGroupOrNull(1, TestMessage.instanceCreator);
2084    expect(msg.getBoolWithDefault(1, false)).toBe(true);
2085  });
2086
2087  it('return group from the input when pivot is set', () => {
2088    const bytes = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C);
2089    const accessor = Kernel.fromArrayBuffer(bytes);
2090    const msg = accessor.getGroupOrNull(1, TestMessage.instanceCreator, 0);
2091    expect(msg.getBoolWithDefault(1, false)).toBe(true);
2092  });
2093
2094  it('encode group from the input', () => {
2095    const bytes = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C);
2096    const accessor = Kernel.fromArrayBuffer(bytes);
2097    expect(accessor.serialize()).toEqual(bytes);
2098  });
2099
2100  it('encode group from the input after read', () => {
2101    const bytes = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C);
2102    const accessor = Kernel.fromArrayBuffer(bytes);
2103    accessor.getGroupOrNull(1, TestMessage.instanceCreator);
2104    expect(accessor.serialize()).toEqual(bytes);
2105  });
2106
2107  it('return last group from multiple inputs', () => {
2108    const bytes =
2109        createArrayBuffer(0x0B, 0x08, 0x00, 0x0C, 0x0B, 0x08, 0x01, 0x0C);
2110    const accessor = Kernel.fromArrayBuffer(bytes);
2111    const msg = accessor.getGroupOrNull(1, TestMessage.instanceCreator);
2112    expect(msg.getBoolWithDefault(1, false)).toBe(true);
2113  });
2114
2115  it('removes duplicated group when serializing', () => {
2116    const bytes =
2117        createArrayBuffer(0x0B, 0x08, 0x00, 0x0C, 0x0B, 0x08, 0x01, 0x0C);
2118    const accessor = Kernel.fromArrayBuffer(bytes);
2119    accessor.getGroupOrNull(1, TestMessage.instanceCreator);
2120    expect(accessor.serialize())
2121        .toEqual(createArrayBuffer(0x0B, 0x08, 0x01, 0x0C));
2122  });
2123
2124  it('encode group from multiple inputs', () => {
2125    const bytes =
2126        createArrayBuffer(0x0B, 0x08, 0x00, 0x0C, 0x0B, 0x08, 0x01, 0x0C);
2127    const accessor = Kernel.fromArrayBuffer(bytes);
2128    expect(accessor.serialize()).toEqual(bytes);
2129  });
2130
2131  it('encode group after read', () => {
2132    const bytes =
2133        createArrayBuffer(0x0B, 0x08, 0x00, 0x0C, 0x0B, 0x08, 0x01, 0x0C);
2134    const expected = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C);
2135    const accessor = Kernel.fromArrayBuffer(bytes);
2136    accessor.getGroupOrNull(1, TestMessage.instanceCreator);
2137    expect(accessor.serialize()).toEqual(expected);
2138  });
2139
2140  it('return group from setter', () => {
2141    const bytes = createArrayBuffer(0x08, 0x01);
2142    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
2143    const subaccessor = Kernel.fromArrayBuffer(bytes);
2144    const submsg1 = new TestMessage(subaccessor);
2145    accessor.setGroup(1, submsg1);
2146    const submsg2 = accessor.getGroup(1, TestMessage.instanceCreator);
2147    expect(submsg1).toBe(submsg2);
2148  });
2149
2150  it('encode group from setter', () => {
2151    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
2152    const subaccessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01));
2153    const submsg = new TestMessage(subaccessor);
2154    accessor.setGroup(1, submsg);
2155    const expected = createArrayBuffer(0x0B, 0x08, 0x01, 0x0C);
2156    expect(accessor.serialize()).toEqual(expected);
2157  });
2158
2159  it('leave hasFieldNumber unchanged after getGroupOrNull', () => {
2160    const accessor = Kernel.createEmpty();
2161    expect(accessor.hasFieldNumber(1)).toBe(false);
2162    expect(accessor.getGroupOrNull(1, TestMessage.instanceCreator)).toBe(null);
2163    expect(accessor.hasFieldNumber(1)).toBe(false);
2164  });
2165
2166  it('serialize changes to subgroups made with getGroupsOrNull', () => {
2167    const intTwoBytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C);
2168    const accessor = Kernel.fromArrayBuffer(intTwoBytes);
2169    const mutableSubMessage =
2170        accessor.getGroupOrNull(1, TestMessage.instanceCreator);
2171    mutableSubMessage.setInt32(1, 10);
2172    const intTenBytes = createArrayBuffer(0x0B, 0x08, 0x0A, 0x0C);
2173    expect(accessor.serialize()).toEqual(intTenBytes);
2174  });
2175
2176  it('serialize additions to subgroups made with getGroupOrNull', () => {
2177    const intTwoBytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C);
2178    const accessor = Kernel.fromArrayBuffer(intTwoBytes);
2179    const mutableSubMessage =
2180        accessor.getGroupOrNull(1, TestMessage.instanceCreator);
2181    mutableSubMessage.setInt32(2, 3);
2182    // Sub group contains the original field, plus the new one.
2183    expect(accessor.serialize())
2184        .toEqual(createArrayBuffer(0x0B, 0x08, 0x02, 0x10, 0x03, 0x0C));
2185  });
2186
2187  it('fail with getGroupOrNull if immutable group exist in cache', () => {
2188    const intTwoBytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C);
2189    const accessor = Kernel.fromArrayBuffer(intTwoBytes);
2190
2191    const readOnly = accessor.getGroup(1, TestMessage.instanceCreator);
2192    if (CHECK_TYPE) {
2193      expect(() => accessor.getGroupOrNull(1, TestMessage.instanceCreator))
2194          .toThrow();
2195    } else {
2196      const mutableSubGropu =
2197          accessor.getGroupOrNull(1, TestMessage.instanceCreator);
2198      // The instance returned by getGroupOrNull is the exact same instance.
2199      expect(mutableSubGropu).toBe(readOnly);
2200
2201      // Serializing the subgroup does not write the changes
2202      mutableSubGropu.setInt32(1, 0);
2203      expect(accessor.serialize()).toEqual(intTwoBytes);
2204    }
2205  });
2206
2207  it('change hasFieldNumber after getGroupAttach', () => {
2208    const accessor = Kernel.createEmpty();
2209    expect(accessor.hasFieldNumber(1)).toBe(false);
2210    expect(accessor.getGroupAttach(1, TestMessage.instanceCreator))
2211        .not.toBe(null);
2212    expect(accessor.hasFieldNumber(1)).toBe(true);
2213  });
2214
2215  it('change hasFieldNumber after getGroupAttach when pivot is set', () => {
2216    const accessor = Kernel.createEmpty();
2217    expect(accessor.hasFieldNumber(1)).toBe(false);
2218    expect(
2219        accessor.getGroupAttach(1, TestMessage.instanceCreator, /* pivot= */ 1))
2220        .not.toBe(null);
2221    expect(accessor.hasFieldNumber(1)).toBe(true);
2222  });
2223
2224  it('serialize subgroups made with getGroupAttach', () => {
2225    const accessor = Kernel.createEmpty();
2226    const mutableSubGroup =
2227        accessor.getGroupAttach(1, TestMessage.instanceCreator);
2228    mutableSubGroup.setInt32(1, 10);
2229    const intTenBytes = createArrayBuffer(0x0B, 0x08, 0x0A, 0x0C);
2230    expect(accessor.serialize()).toEqual(intTenBytes);
2231  });
2232
2233  it('serialize additions to subgroups using getMessageAttach', () => {
2234    const intTwoBytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C);
2235    const accessor = Kernel.fromArrayBuffer(intTwoBytes);
2236    const mutableSubGroup =
2237        accessor.getGroupAttach(1, TestMessage.instanceCreator);
2238    mutableSubGroup.setInt32(2, 3);
2239    // Sub message contains the original field, plus the new one.
2240    expect(accessor.serialize())
2241        .toEqual(createArrayBuffer(0x0B, 0x08, 0x02, 0x10, 0x03, 0x0C));
2242  });
2243
2244  it('fail with getGroupAttach if immutable message exist in cache', () => {
2245    const intTwoBytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C);
2246    const accessor = Kernel.fromArrayBuffer(intTwoBytes);
2247
2248    const readOnly = accessor.getGroup(1, TestMessage.instanceCreator);
2249    if (CHECK_TYPE) {
2250      expect(() => accessor.getGroupAttach(1, TestMessage.instanceCreator))
2251          .toThrow();
2252    } else {
2253      const mutableSubGroup =
2254          accessor.getGroupAttach(1, TestMessage.instanceCreator);
2255      // The instance returned by getMessageOrNull is the exact same instance.
2256      expect(mutableSubGroup).toBe(readOnly);
2257
2258      // Serializing the submessage does not write the changes
2259      mutableSubGroup.setInt32(1, 0);
2260      expect(accessor.serialize()).toEqual(intTwoBytes);
2261    }
2262  });
2263
2264  it('read default group return empty group with getGroup', () => {
2265    const bytes = new ArrayBuffer(0);
2266    const accessor = Kernel.fromArrayBuffer(bytes);
2267    expect(accessor.getGroup(1, TestMessage.instanceCreator)).toBeTruthy();
2268    expect(accessor.getGroup(1, TestMessage.instanceCreator).serialize())
2269        .toEqual(bytes);
2270  });
2271
2272  it('read default group return null with getGroupOrNull', () => {
2273    const bytes = new ArrayBuffer(0);
2274    const accessor = Kernel.fromArrayBuffer(bytes);
2275    expect(accessor.getGroupOrNull(1, TestMessage.instanceCreator)).toBe(null);
2276  });
2277
2278  it('read group preserve reference equality', () => {
2279    const bytes = createArrayBuffer(0x0B, 0x08, 0x02, 0x0C);
2280    const accessor = Kernel.fromArrayBuffer(bytes);
2281    const msg1 = accessor.getGroupOrNull(1, TestMessage.instanceCreator);
2282    const msg2 = accessor.getGroupOrNull(1, TestMessage.instanceCreator);
2283    const msg3 = accessor.getGroupAttach(1, TestMessage.instanceCreator);
2284    expect(msg1).toBe(msg2);
2285    expect(msg1).toBe(msg3);
2286  });
2287
2288  it('fail when getting group with null instance constructor', () => {
2289    const accessor =
2290        Kernel.fromArrayBuffer(createArrayBuffer(0x0A, 0x02, 0x08, 0x01));
2291    const nullMessage = /** @type {function(!Kernel):!TestMessage} */
2292        (/** @type {*} */ (null));
2293    expect(() => accessor.getGroupOrNull(1, nullMessage)).toThrow();
2294  });
2295
2296  it('fail when setting group value with null value', () => {
2297    const accessor = Kernel.fromArrayBuffer(new ArrayBuffer(0));
2298    const fakeMessage = /** @type {!TestMessage} */ (/** @type {*} */ (null));
2299    if (CHECK_CRITICAL_TYPE) {
2300      expect(() => accessor.setGroup(1, fakeMessage))
2301          .toThrowError('Given value is not a message instance: null');
2302    } else {
2303      // Note in unchecked mode we produce invalid output for invalid inputs.
2304      // This test just documents our behavior in those cases.
2305      // These values might change at any point and are not considered
2306      // what the implementation should be doing here.
2307      accessor.setMessage(1, fakeMessage);
2308      expect(accessor.getGroupOrNull(
2309                 /* fieldNumber= */ 1, TestMessage.instanceCreator))
2310          .toBeNull();
2311    }
2312  });
2313
2314  it('reads group in a longer buffer', () => {
2315    const bytes = createArrayBuffer(
2316        0x12, 0x20,  // 32 length delimited
2317        0x00,        // random values for padding start
2318        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2319        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2320        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2321        0x00,  // random values for padding end
2322        0x0B,  // Group tag
2323        0x08, 0x02, 0x0C);
2324    const accessor = Kernel.fromArrayBuffer(bytes);
2325    const msg1 = accessor.getGroupOrNull(1, TestMessage.instanceCreator);
2326    const msg2 = accessor.getGroupOrNull(1, TestMessage.instanceCreator);
2327    expect(msg1).toBe(msg2);
2328  });
2329});
2330