1ffe3c632Sopenharmony_ci/**
2ffe3c632Sopenharmony_ci * @fileoverview Tests to make sure Kernel can read data in a backward
3ffe3c632Sopenharmony_ci * compatible way even when protobuf schema changes according to the rules
4ffe3c632Sopenharmony_ci * defined in
5ffe3c632Sopenharmony_ci * https://developers.google.com/protocol-buffers/docs/proto#updating and
6ffe3c632Sopenharmony_ci * https://developers.google.com/protocol-buffers/docs/proto3#updating.
7ffe3c632Sopenharmony_ci *
8ffe3c632Sopenharmony_ci * third_party/protobuf/conformance/binary_json_conformance_suite.cc already
9ffe3c632Sopenharmony_ci * covers many compatibility tests, this file covers only the tests not covered
10ffe3c632Sopenharmony_ci * by binary_json_conformance_suite. Ultimately all of the tests in this file
11ffe3c632Sopenharmony_ci * should be moved to binary_json_conformance_suite.
12ffe3c632Sopenharmony_ci */
13ffe3c632Sopenharmony_cigoog.module('protobuf.runtime.KernelCompatibilityTest');
14ffe3c632Sopenharmony_ci
15ffe3c632Sopenharmony_cigoog.setTestOnly();
16ffe3c632Sopenharmony_ci
17ffe3c632Sopenharmony_ciconst ByteString = goog.require('protobuf.ByteString');
18ffe3c632Sopenharmony_ciconst Int64 = goog.require('protobuf.Int64');
19ffe3c632Sopenharmony_ciconst Kernel = goog.require('protobuf.runtime.Kernel');
20ffe3c632Sopenharmony_ciconst TestMessage = goog.require('protobuf.testing.binary.TestMessage');
21ffe3c632Sopenharmony_ciconst {CHECK_CRITICAL_STATE} = goog.require('protobuf.internal.checks');
22ffe3c632Sopenharmony_ci
23ffe3c632Sopenharmony_ci/**
24ffe3c632Sopenharmony_ci * @param {...number} bytes
25ffe3c632Sopenharmony_ci * @return {!ArrayBuffer}
26ffe3c632Sopenharmony_ci */
27ffe3c632Sopenharmony_cifunction createArrayBuffer(...bytes) {
28ffe3c632Sopenharmony_ci  return new Uint8Array(bytes).buffer;
29ffe3c632Sopenharmony_ci}
30ffe3c632Sopenharmony_ci
31ffe3c632Sopenharmony_ci/**
32ffe3c632Sopenharmony_ci * Returns the Unicode character codes of a string.
33ffe3c632Sopenharmony_ci * @param {string} str
34ffe3c632Sopenharmony_ci * @return {!Array<number>}
35ffe3c632Sopenharmony_ci */
36ffe3c632Sopenharmony_cifunction getCharacterCodes(str) {
37ffe3c632Sopenharmony_ci  return Array.from(str, (c) => c.charCodeAt(0));
38ffe3c632Sopenharmony_ci}
39ffe3c632Sopenharmony_ci
40ffe3c632Sopenharmony_cidescribe('optional -> repeated compatibility', () => {
41ffe3c632Sopenharmony_ci  it('is maintained for scalars', () => {
42ffe3c632Sopenharmony_ci    const oldAccessor = Kernel.createEmpty();
43ffe3c632Sopenharmony_ci    oldAccessor.setInt32(1, 1);
44ffe3c632Sopenharmony_ci    const serializedData = oldAccessor.serialize();
45ffe3c632Sopenharmony_ci    expect(serializedData).toEqual(createArrayBuffer(0x8, 0x1));
46ffe3c632Sopenharmony_ci
47ffe3c632Sopenharmony_ci    const newAccessor = Kernel.fromArrayBuffer(serializedData);
48ffe3c632Sopenharmony_ci    expect(newAccessor.getRepeatedInt32Size(1)).toEqual(1);
49ffe3c632Sopenharmony_ci    expect(newAccessor.getRepeatedInt32Element(1, 0)).toEqual(1);
50ffe3c632Sopenharmony_ci  });
51ffe3c632Sopenharmony_ci
52ffe3c632Sopenharmony_ci  it('is maintained for messages', () => {
53ffe3c632Sopenharmony_ci    const message = new TestMessage(Kernel.createEmpty());
54ffe3c632Sopenharmony_ci    message.setInt32(1, 1);
55ffe3c632Sopenharmony_ci
56ffe3c632Sopenharmony_ci    const oldAccessor = Kernel.createEmpty();
57ffe3c632Sopenharmony_ci    oldAccessor.setMessage(1, message);
58ffe3c632Sopenharmony_ci    const serializedData = oldAccessor.serialize();
59ffe3c632Sopenharmony_ci    expect(serializedData).toEqual(createArrayBuffer(0xA, 0x2, 0x8, 0x1));
60ffe3c632Sopenharmony_ci
61ffe3c632Sopenharmony_ci    const newAccessor = Kernel.fromArrayBuffer(serializedData);
62ffe3c632Sopenharmony_ci    expect(newAccessor.getRepeatedMessageSize(1, TestMessage.instanceCreator))
63ffe3c632Sopenharmony_ci        .toEqual(1);
64ffe3c632Sopenharmony_ci    expect(
65ffe3c632Sopenharmony_ci        newAccessor.getRepeatedMessageElement(1, TestMessage.instanceCreator, 0)
66ffe3c632Sopenharmony_ci            .serialize())
67ffe3c632Sopenharmony_ci        .toEqual(message.serialize());
68ffe3c632Sopenharmony_ci  });
69ffe3c632Sopenharmony_ci
70ffe3c632Sopenharmony_ci  it('is maintained for bytes', () => {
71ffe3c632Sopenharmony_ci    const message = new TestMessage(Kernel.createEmpty());
72ffe3c632Sopenharmony_ci    message.setInt32(1, 1);
73ffe3c632Sopenharmony_ci
74ffe3c632Sopenharmony_ci    const oldAccessor = Kernel.createEmpty();
75ffe3c632Sopenharmony_ci    oldAccessor.setBytes(
76ffe3c632Sopenharmony_ci        1, ByteString.fromArrayBuffer(createArrayBuffer(0xA, 0xB)));
77ffe3c632Sopenharmony_ci    const serializedData = oldAccessor.serialize();
78ffe3c632Sopenharmony_ci    expect(serializedData).toEqual(createArrayBuffer(0xA, 0x2, 0xA, 0xB));
79ffe3c632Sopenharmony_ci
80ffe3c632Sopenharmony_ci    const newAccessor = Kernel.fromArrayBuffer(serializedData);
81ffe3c632Sopenharmony_ci    expect(newAccessor.getRepeatedBytesSize(1)).toEqual(1);
82ffe3c632Sopenharmony_ci    expect(newAccessor.getRepeatedBoolElement(1, 0))
83ffe3c632Sopenharmony_ci        .toEqual(ByteString.fromArrayBuffer(createArrayBuffer(0xA, 0xB)));
84ffe3c632Sopenharmony_ci  });
85ffe3c632Sopenharmony_ci
86ffe3c632Sopenharmony_ci  it('is maintained for strings', () => {
87ffe3c632Sopenharmony_ci    const oldAccessor = Kernel.createEmpty();
88ffe3c632Sopenharmony_ci    oldAccessor.setString(1, 'hello');
89ffe3c632Sopenharmony_ci    const serializedData = oldAccessor.serialize();
90ffe3c632Sopenharmony_ci    expect(serializedData)
91ffe3c632Sopenharmony_ci        .toEqual(createArrayBuffer(0xA, 0x5, 0x68, 0x65, 0x6C, 0x6C, 0x6F));
92ffe3c632Sopenharmony_ci
93ffe3c632Sopenharmony_ci    const newAccessor = Kernel.fromArrayBuffer(serializedData);
94ffe3c632Sopenharmony_ci    expect(newAccessor.getRepeatedStringSize(1)).toEqual(1);
95ffe3c632Sopenharmony_ci    expect(newAccessor.getRepeatedStringElement(1, 0)).toEqual('hello');
96ffe3c632Sopenharmony_ci  });
97ffe3c632Sopenharmony_ci});
98ffe3c632Sopenharmony_ci
99ffe3c632Sopenharmony_cidescribe('Kernel repeated -> optional compatibility', () => {
100ffe3c632Sopenharmony_ci  it('is maintained for unpacked scalars', () => {
101ffe3c632Sopenharmony_ci    const oldAccessor = Kernel.createEmpty();
102ffe3c632Sopenharmony_ci    oldAccessor.addUnpackedInt32Element(1, 0);
103ffe3c632Sopenharmony_ci    oldAccessor.addUnpackedInt32Element(1, 1);
104ffe3c632Sopenharmony_ci    const serializedData = oldAccessor.serialize();
105ffe3c632Sopenharmony_ci    expect(serializedData).toEqual(createArrayBuffer(0x8, 0x0, 0x8, 0x1));
106ffe3c632Sopenharmony_ci
107ffe3c632Sopenharmony_ci    const newAccessor = Kernel.fromArrayBuffer(serializedData);
108ffe3c632Sopenharmony_ci    expect(newAccessor.getInt32WithDefault(1)).toEqual(1);
109ffe3c632Sopenharmony_ci    expect(newAccessor.serialize()).toEqual(serializedData);
110ffe3c632Sopenharmony_ci  });
111ffe3c632Sopenharmony_ci
112ffe3c632Sopenharmony_ci  // repeated -> optional transformation is not supported for packed fields yet:
113ffe3c632Sopenharmony_ci  // go/proto-schema-repeated
114ffe3c632Sopenharmony_ci  it('is not maintained for packed scalars', () => {
115ffe3c632Sopenharmony_ci    const oldAccessor = Kernel.createEmpty();
116ffe3c632Sopenharmony_ci    oldAccessor.addPackedInt32Element(1, 0);
117ffe3c632Sopenharmony_ci    oldAccessor.addPackedInt32Element(1, 1);
118ffe3c632Sopenharmony_ci    const serializedData = oldAccessor.serialize();
119ffe3c632Sopenharmony_ci    expect(serializedData).toEqual(createArrayBuffer(0xA, 0x2, 0x0, 0x1));
120ffe3c632Sopenharmony_ci
121ffe3c632Sopenharmony_ci    const newAccessor = Kernel.fromArrayBuffer(serializedData);
122ffe3c632Sopenharmony_ci    if (CHECK_CRITICAL_STATE) {
123ffe3c632Sopenharmony_ci      expect(() => newAccessor.getInt32WithDefault(1)).toThrow();
124ffe3c632Sopenharmony_ci    }
125ffe3c632Sopenharmony_ci  });
126ffe3c632Sopenharmony_ci
127ffe3c632Sopenharmony_ci  it('is maintained for messages', () => {
128ffe3c632Sopenharmony_ci    const message1 = new TestMessage(Kernel.createEmpty());
129ffe3c632Sopenharmony_ci    message1.setInt32(1, 1);
130ffe3c632Sopenharmony_ci    const message2 = new TestMessage(Kernel.createEmpty());
131ffe3c632Sopenharmony_ci    message2.setInt32(1, 2);
132ffe3c632Sopenharmony_ci    message2.setInt32(2, 3);
133ffe3c632Sopenharmony_ci
134ffe3c632Sopenharmony_ci    const oldAccessor = Kernel.createEmpty();
135ffe3c632Sopenharmony_ci    oldAccessor.addRepeatedMessageElement(
136ffe3c632Sopenharmony_ci        1, message1, TestMessage.instanceCreator);
137ffe3c632Sopenharmony_ci    oldAccessor.addRepeatedMessageElement(
138ffe3c632Sopenharmony_ci        1, message2, TestMessage.instanceCreator);
139ffe3c632Sopenharmony_ci    const serializedData = oldAccessor.serialize();
140ffe3c632Sopenharmony_ci    expect(serializedData)
141ffe3c632Sopenharmony_ci        .toEqual(createArrayBuffer(
142ffe3c632Sopenharmony_ci            0xA, 0x2, 0x8, 0x1, 0xA, 0x4, 0x8, 0x2, 0x10, 0x3));
143ffe3c632Sopenharmony_ci
144ffe3c632Sopenharmony_ci    const newAccessor = Kernel.fromArrayBuffer(serializedData);
145ffe3c632Sopenharmony_ci    // Values from message1 and message2 have been merged
146ffe3c632Sopenharmony_ci    const newMessage = newAccessor.getMessage(1, TestMessage.instanceCreator);
147ffe3c632Sopenharmony_ci    expect(newMessage.getRepeatedInt32Size(1)).toEqual(2);
148ffe3c632Sopenharmony_ci    expect(newMessage.getRepeatedInt32Element(1, 0)).toEqual(1);
149ffe3c632Sopenharmony_ci    expect(newMessage.getRepeatedInt32Element(1, 1)).toEqual(2);
150ffe3c632Sopenharmony_ci    expect(newMessage.getInt32WithDefault(2)).toEqual(3);
151ffe3c632Sopenharmony_ci    expect(newMessage.serialize())
152ffe3c632Sopenharmony_ci        .toEqual(createArrayBuffer(0x8, 0x1, 0x8, 0x2, 0x10, 0x3));
153ffe3c632Sopenharmony_ci  });
154ffe3c632Sopenharmony_ci
155ffe3c632Sopenharmony_ci  it('is maintained for bytes', () => {
156ffe3c632Sopenharmony_ci    const oldAccessor = Kernel.createEmpty();
157ffe3c632Sopenharmony_ci    oldAccessor.addRepeatedBytesElement(
158ffe3c632Sopenharmony_ci        1, ByteString.fromArrayBuffer(createArrayBuffer(0xA, 0xB)));
159ffe3c632Sopenharmony_ci    oldAccessor.addRepeatedBytesElement(
160ffe3c632Sopenharmony_ci        1, ByteString.fromArrayBuffer(createArrayBuffer(0xC, 0xD)));
161ffe3c632Sopenharmony_ci    const serializedData = oldAccessor.serialize();
162ffe3c632Sopenharmony_ci    expect(serializedData)
163ffe3c632Sopenharmony_ci        .toEqual(createArrayBuffer(0xA, 0x2, 0xA, 0xB, 0xA, 0x2, 0xC, 0xD));
164ffe3c632Sopenharmony_ci
165ffe3c632Sopenharmony_ci    const newAccessor = Kernel.fromArrayBuffer(serializedData);
166ffe3c632Sopenharmony_ci    expect(newAccessor.getBytesWithDefault(1))
167ffe3c632Sopenharmony_ci        .toEqual(ByteString.fromArrayBuffer(createArrayBuffer(0xC, 0xD)));
168ffe3c632Sopenharmony_ci    expect(newAccessor.serialize()).toEqual(serializedData);
169ffe3c632Sopenharmony_ci  });
170ffe3c632Sopenharmony_ci
171ffe3c632Sopenharmony_ci  it('is maintained for strings', () => {
172ffe3c632Sopenharmony_ci    const oldAccessor = Kernel.createEmpty();
173ffe3c632Sopenharmony_ci    oldAccessor.addRepeatedStringElement(1, 'hello');
174ffe3c632Sopenharmony_ci    oldAccessor.addRepeatedStringElement(1, 'world');
175ffe3c632Sopenharmony_ci    const serializedData = oldAccessor.serialize();
176ffe3c632Sopenharmony_ci    expect(serializedData)
177ffe3c632Sopenharmony_ci        .toEqual(createArrayBuffer(
178ffe3c632Sopenharmony_ci            0xA, 0x5, ...getCharacterCodes('hello'), 0xA, 0x5,
179ffe3c632Sopenharmony_ci            ...getCharacterCodes('world')));
180ffe3c632Sopenharmony_ci
181ffe3c632Sopenharmony_ci    const newAccessor = Kernel.fromArrayBuffer(serializedData);
182ffe3c632Sopenharmony_ci    expect(newAccessor.getStringWithDefault(1)).toEqual('world');
183ffe3c632Sopenharmony_ci    expect(newAccessor.serialize()).toEqual(serializedData);
184ffe3c632Sopenharmony_ci  });
185ffe3c632Sopenharmony_ci});
186ffe3c632Sopenharmony_ci
187ffe3c632Sopenharmony_cidescribe('Type change', () => {
188ffe3c632Sopenharmony_ci  it('is supported for fixed32 -> sfixed32', () => {
189ffe3c632Sopenharmony_ci    const oldAccessor = Kernel.createEmpty();
190ffe3c632Sopenharmony_ci    oldAccessor.setFixed32(1, 4294967295);
191ffe3c632Sopenharmony_ci    const serializedData = oldAccessor.serialize();
192ffe3c632Sopenharmony_ci    expect(serializedData)
193ffe3c632Sopenharmony_ci        .toEqual(createArrayBuffer(0xD, 0xFF, 0xFF, 0xFF, 0xFF));
194ffe3c632Sopenharmony_ci
195ffe3c632Sopenharmony_ci    const newAccessor = Kernel.fromArrayBuffer(serializedData);
196ffe3c632Sopenharmony_ci    expect(newAccessor.getSfixed32WithDefault(1)).toEqual(-1);
197ffe3c632Sopenharmony_ci    expect(newAccessor.serialize()).toEqual(serializedData);
198ffe3c632Sopenharmony_ci  });
199ffe3c632Sopenharmony_ci
200ffe3c632Sopenharmony_ci  it('is supported for sfixed32 -> fixed32', () => {
201ffe3c632Sopenharmony_ci    const oldAccessor = Kernel.createEmpty();
202ffe3c632Sopenharmony_ci    oldAccessor.setSfixed32(1, -1);
203ffe3c632Sopenharmony_ci    const serializedData = oldAccessor.serialize();
204ffe3c632Sopenharmony_ci    expect(serializedData)
205ffe3c632Sopenharmony_ci        .toEqual(createArrayBuffer(0xD, 0xFF, 0xFF, 0xFF, 0xFF));
206ffe3c632Sopenharmony_ci
207ffe3c632Sopenharmony_ci    const newAccessor = Kernel.fromArrayBuffer(serializedData);
208ffe3c632Sopenharmony_ci    expect(newAccessor.getFixed32WithDefault(1)).toEqual(4294967295);
209ffe3c632Sopenharmony_ci    expect(newAccessor.serialize()).toEqual(serializedData);
210ffe3c632Sopenharmony_ci  });
211ffe3c632Sopenharmony_ci
212ffe3c632Sopenharmony_ci  it('is supported for fixed64 -> sfixed64', () => {
213ffe3c632Sopenharmony_ci    const oldAccessor = Kernel.createEmpty();
214ffe3c632Sopenharmony_ci    oldAccessor.setFixed64(1, Int64.fromHexString('0xFFFFFFFFFFFFFFFF'));
215ffe3c632Sopenharmony_ci    const serializedData = oldAccessor.serialize();
216ffe3c632Sopenharmony_ci    expect(serializedData)
217ffe3c632Sopenharmony_ci        .toEqual(createArrayBuffer(
218ffe3c632Sopenharmony_ci            0x9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF));
219ffe3c632Sopenharmony_ci
220ffe3c632Sopenharmony_ci    const newAccessor = Kernel.fromArrayBuffer(serializedData);
221ffe3c632Sopenharmony_ci    expect(newAccessor.getSfixed64WithDefault(1)).toEqual(Int64.fromInt(-1));
222ffe3c632Sopenharmony_ci    expect(newAccessor.serialize()).toEqual(serializedData);
223ffe3c632Sopenharmony_ci  });
224ffe3c632Sopenharmony_ci
225ffe3c632Sopenharmony_ci  it('is supported for sfixed64 -> fixed64', () => {
226ffe3c632Sopenharmony_ci    const oldAccessor = Kernel.createEmpty();
227ffe3c632Sopenharmony_ci    oldAccessor.setSfixed64(1, Int64.fromInt(-1));
228ffe3c632Sopenharmony_ci    const serializedData = oldAccessor.serialize();
229ffe3c632Sopenharmony_ci    expect(serializedData)
230ffe3c632Sopenharmony_ci        .toEqual(createArrayBuffer(
231ffe3c632Sopenharmony_ci            0x9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF));
232ffe3c632Sopenharmony_ci
233ffe3c632Sopenharmony_ci    const newAccessor = Kernel.fromArrayBuffer(serializedData);
234ffe3c632Sopenharmony_ci    expect(newAccessor.getFixed64WithDefault(1))
235ffe3c632Sopenharmony_ci        .toEqual(Int64.fromHexString('0xFFFFFFFFFFFFFFFF'));
236ffe3c632Sopenharmony_ci    expect(newAccessor.serialize()).toEqual(serializedData);
237ffe3c632Sopenharmony_ci  });
238ffe3c632Sopenharmony_ci
239ffe3c632Sopenharmony_ci  it('is supported for bytes -> message', () => {
240ffe3c632Sopenharmony_ci    const oldAccessor = Kernel.createEmpty();
241ffe3c632Sopenharmony_ci    oldAccessor.setBytes(
242ffe3c632Sopenharmony_ci        1, ByteString.fromArrayBuffer(createArrayBuffer(0x8, 0x1)));
243ffe3c632Sopenharmony_ci    const serializedData = oldAccessor.serialize();
244ffe3c632Sopenharmony_ci    expect(serializedData).toEqual(createArrayBuffer(0xA, 0x2, 0x8, 0x1));
245ffe3c632Sopenharmony_ci
246ffe3c632Sopenharmony_ci    const newAccessor = Kernel.fromArrayBuffer(serializedData);
247ffe3c632Sopenharmony_ci    const message = newAccessor.getMessage(1, TestMessage.instanceCreator);
248ffe3c632Sopenharmony_ci    expect(message.getInt32WithDefault(1)).toEqual(1);
249ffe3c632Sopenharmony_ci    expect(message.serialize()).toEqual(createArrayBuffer(0x8, 0x1));
250ffe3c632Sopenharmony_ci    expect(newAccessor.serialize()).toEqual(serializedData);
251ffe3c632Sopenharmony_ci  });
252ffe3c632Sopenharmony_ci
253ffe3c632Sopenharmony_ci  it('is supported for message -> bytes', () => {
254ffe3c632Sopenharmony_ci    const oldAccessor = Kernel.createEmpty();
255ffe3c632Sopenharmony_ci    const message = new TestMessage(Kernel.createEmpty());
256ffe3c632Sopenharmony_ci    message.setInt32(1, 1);
257ffe3c632Sopenharmony_ci    oldAccessor.setMessage(1, message);
258ffe3c632Sopenharmony_ci    const serializedData = oldAccessor.serialize();
259ffe3c632Sopenharmony_ci    expect(serializedData).toEqual(createArrayBuffer(0xA, 0x2, 0x8, 0x1));
260ffe3c632Sopenharmony_ci
261ffe3c632Sopenharmony_ci    const newAccessor = Kernel.fromArrayBuffer(serializedData);
262ffe3c632Sopenharmony_ci    expect(newAccessor.getBytesWithDefault(1))
263ffe3c632Sopenharmony_ci        .toEqual(ByteString.fromArrayBuffer(createArrayBuffer(0x8, 0x1)));
264ffe3c632Sopenharmony_ci    expect(newAccessor.serialize()).toEqual(serializedData);
265ffe3c632Sopenharmony_ci  });
266ffe3c632Sopenharmony_ci});
267