• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * @fileoverview Tests for message_set.js.
3 */
4goog.module('protobuf.runtime.MessageSetTest');
5
6goog.setTestOnly();
7
8const Kernel = goog.require('protobuf.runtime.Kernel');
9const MessageSet = goog.require('protobuf.runtime.MessageSet');
10const TestMessage = goog.require('protobuf.testing.binary.TestMessage');
11
12/**
13 * @param {...number} bytes
14 * @return {!ArrayBuffer}
15 */
16function createArrayBuffer(...bytes) {
17  return new Uint8Array(bytes).buffer;
18}
19
20describe('MessageSet does', () => {
21  it('returns no messages for empty set', () => {
22    const messageSet = MessageSet.createEmpty();
23    expect(messageSet.getMessageOrNull(12345, TestMessage.instanceCreator))
24        .toBeNull();
25  });
26
27  it('returns no kernel for empty set', () => {
28    const messageSet = MessageSet.createEmpty();
29    expect(messageSet.getMessageAccessorOrNull(12345)).toBeNull();
30  });
31
32  it('returns message that has been set', () => {
33    const messageSet = MessageSet.createEmpty();
34    const message = TestMessage.createEmpty();
35    messageSet.setMessage(12345, message);
36    expect(messageSet.getMessageOrNull(12345, TestMessage.instanceCreator))
37        .toBe(message);
38  });
39
40  it('returns null for cleared message', () => {
41    const messageSet = MessageSet.createEmpty();
42    const message = TestMessage.createEmpty();
43    messageSet.setMessage(12345, message);
44    messageSet.clearMessage(12345);
45    expect(messageSet.getMessageAccessorOrNull(12345)).toBeNull();
46  });
47
48  it('returns false for not present message', () => {
49    const messageSet = MessageSet.createEmpty();
50    expect(messageSet.hasMessage(12345)).toBe(false);
51  });
52
53  it('returns true for present message', () => {
54    const messageSet = MessageSet.createEmpty();
55    const message = TestMessage.createEmpty();
56    messageSet.setMessage(12345, message);
57    expect(messageSet.hasMessage(12345)).toBe(true);
58  });
59
60  it('returns false for cleared message', () => {
61    const messageSet = MessageSet.createEmpty();
62    const message = TestMessage.createEmpty();
63    messageSet.setMessage(12345, message);
64    messageSet.clearMessage(12345);
65    expect(messageSet.hasMessage(12345)).toBe(false);
66  });
67
68  it('returns false for cleared message without it being present', () => {
69    const messageSet = MessageSet.createEmpty();
70    messageSet.clearMessage(12345);
71    expect(messageSet.hasMessage(12345)).toBe(false);
72  });
73
74  const createMessageSet = () => {
75    const messageSet = MessageSet.createEmpty();
76    const message = TestMessage.createEmpty();
77    message.setInt32(1, 2);
78    messageSet.setMessage(12345, message);
79
80
81    const parsedKernel =
82        Kernel.fromArrayBuffer(messageSet.internalGetKernel().serialize());
83    return MessageSet.fromKernel(parsedKernel);
84  };
85
86  it('pass through pivot for getMessageOrNull', () => {
87    const messageSet = createMessageSet();
88    const message =
89        messageSet.getMessageOrNull(12345, TestMessage.instanceCreator, 2);
90    expect(message.internalGetKernel().getPivot()).toBe(2);
91  });
92
93  it('pass through pivot for getMessageAttach', () => {
94    const messageSet = createMessageSet();
95    const message =
96        messageSet.getMessageAttach(12345, TestMessage.instanceCreator, 2);
97    expect(message.internalGetKernel().getPivot()).toBe(2);
98  });
99
100  it('pass through pivot for getMessageAccessorOrNull', () => {
101    const messageSet = createMessageSet();
102    const kernel = messageSet.getMessageAccessorOrNull(12345, 2);
103    expect(kernel.getPivot()).toBe(2);
104  });
105
106  it('pick the last value in the stream', () => {
107    const arrayBuffer = createArrayBuffer(
108        0x52,  // Tag (field:10, length delimited)
109        0x14,  // Length of 20 bytes
110        0x0B,  // Start group fieldnumber 1
111        0x10,  // Tag (field 2, varint)
112        0xB9,  // 12345
113        0x60,  // 12345
114        0x1A,  // Tag (field 3, length delimited)
115        0x03,  // length 3
116        0xA0,  // Tag (fieldnumber 20, varint)
117        0x01,  // Tag (fieldnumber 20, varint)
118        0x1E,  // 30
119        0x0C,  // Stop Group field number 1
120        // second group
121        0x0B,  // Start group fieldnumber 1
122        0x10,  // Tag (field 2, varint)
123        0xB9,  // 12345
124        0x60,  // 12345
125        0x1A,  // Tag (field 3, length delimited)
126        0x03,  // length 3
127        0xA0,  // Tag (fieldnumber 20, varint)
128        0x01,  // Tag (fieldnumber 20, varint)
129        0x01,  // 1
130        0x0C   // Stop Group field number 1
131    );
132
133    const outerMessage = Kernel.fromArrayBuffer(arrayBuffer);
134
135    const messageSet = outerMessage.getMessage(10, MessageSet.fromKernel);
136
137    const message =
138        messageSet.getMessageOrNull(12345, TestMessage.instanceCreator);
139    expect(message.getInt32WithDefault(20)).toBe(1);
140  });
141
142  it('removes duplicates when read', () => {
143    const arrayBuffer = createArrayBuffer(
144        0x52,  // Tag (field:10, length delimited)
145        0x14,  // Length of 20 bytes
146        0x0B,  // Start group fieldnumber 1
147        0x10,  // Tag (field 2, varint)
148        0xB9,  // 12345
149        0x60,  // 12345
150        0x1A,  // Tag (field 3, length delimited)
151        0x03,  // length 3
152        0xA0,  // Tag (fieldnumber 20, varint)
153        0x01,  // Tag (fieldnumber 20, varint)
154        0x1E,  // 30
155        0x0C,  // Stop Group field number 1
156        // second group
157        0x0B,  // Start group fieldnumber 1
158        0x10,  // Tag (field 2, varint)
159        0xB9,  // 12345
160        0x60,  // 12345
161        0x1A,  // Tag (field 3, length delimited)
162        0x03,  // length 3
163        0xA0,  // Tag (fieldnumber 20, varint)
164        0x01,  // Tag (fieldnumber 20, varint)
165        0x01,  // 1
166        0x0C   // Stop Group field number 1
167    );
168
169
170    const outerMessage = Kernel.fromArrayBuffer(arrayBuffer);
171    outerMessage.getMessageAttach(10, MessageSet.fromKernel);
172
173    expect(outerMessage.serialize())
174        .toEqual(createArrayBuffer(
175            0x52,  // Tag (field:10, length delimited)
176            0x0A,  // Length of 10 bytes
177            0x0B,  // Start group fieldnumber 1
178            0x10,  // Tag (field 2, varint)
179            0xB9,  // 12345
180            0x60,  // 12345
181            0x1A,  // Tag (field 3, length delimited)
182            0x03,  // length 3
183            0xA0,  // Tag (fieldnumber 20, varint)
184            0x01,  // Tag (fieldnumber 20, varint)
185            0x01,  // 1
186            0x0C   // Stop Group field number 1
187            ));
188  });
189
190  it('allow for large typeIds', () => {
191    const messageSet = MessageSet.createEmpty();
192    const message = TestMessage.createEmpty();
193    messageSet.setMessage(0xFFFFFFFE >>> 0, message);
194    expect(messageSet.hasMessage(0xFFFFFFFE >>> 0)).toBe(true);
195  });
196});
197
198describe('Optional MessageSet does', () => {
199  // message Bar {
200  //  optional MessageSet mset = 10;
201  //}
202  //
203  // message Foo {
204  //  extend proto2.bridge.MessageSet {
205  //    optional Foo message_set_extension = 12345;
206  //  }
207  //  optional int32 f20 = 20;
208  //}
209
210  it('encode as a field', () => {
211    const fooMessage = Kernel.createEmpty();
212    fooMessage.setInt32(20, 30);
213
214    const messageSet = MessageSet.createEmpty();
215    messageSet.setMessage(12345, TestMessage.instanceCreator(fooMessage));
216
217    const barMessage = Kernel.createEmpty();
218    barMessage.setMessage(10, messageSet);
219
220    expect(barMessage.serialize())
221        .toEqual(createArrayBuffer(
222            0x52,  // Tag (field:10, length delimited)
223            0x0A,  // Length of 10 bytes
224            0x0B,  // Start group fieldnumber 1
225            0x10,  // Tag (field 2, varint)
226            0xB9,  // 12345
227            0x60,  // 12345
228            0x1A,  // Tag (field 3, length delimited)
229            0x03,  // length 3
230            0xA0,  // Tag (fieldnumber 20, varint)
231            0x01,  // Tag (fieldnumber 20, varint)
232            0x1E,  // 30
233            0x0C   // Stop Group field number 1
234            ));
235  });
236
237  it('deserializes', () => {
238    const fooMessage = Kernel.createEmpty();
239    fooMessage.setInt32(20, 30);
240
241    const messageSet = MessageSet.createEmpty();
242    messageSet.setMessage(12345, TestMessage.instanceCreator(fooMessage));
243
244
245    const barMessage = Kernel.createEmpty();
246    barMessage.setMessage(10, messageSet);
247
248    const arrayBuffer = barMessage.serialize();
249
250    const barMessageParsed = Kernel.fromArrayBuffer(arrayBuffer);
251    expect(barMessageParsed.hasFieldNumber(10)).toBe(true);
252
253    const messageSetParsed =
254        barMessageParsed.getMessage(10, MessageSet.fromKernel);
255
256    const fooMessageParsed =
257        messageSetParsed.getMessageOrNull(12345, TestMessage.instanceCreator)
258            .internalGetKernel();
259
260    expect(fooMessageParsed.getInt32WithDefault(20)).toBe(30);
261  });
262});
263