| /** |
| * @fileoverview Tests for message_set.js. |
| */ |
| goog.module('protobuf.runtime.MessageSetTest'); |
| |
| goog.setTestOnly(); |
| |
| const Kernel = goog.require('protobuf.runtime.Kernel'); |
| const MessageSet = goog.require('protobuf.runtime.MessageSet'); |
| const TestMessage = goog.require('protobuf.testing.binary.TestMessage'); |
| |
| /** |
| * @param {...number} bytes |
| * @return {!ArrayBuffer} |
| */ |
| function createArrayBuffer(...bytes) { |
| return new Uint8Array(bytes).buffer; |
| } |
| |
| describe('MessageSet does', () => { |
| it('returns no messages for empty set', () => { |
| const messageSet = MessageSet.createEmpty(); |
| expect(messageSet.getMessageOrNull(12345, TestMessage.instanceCreator)) |
| .toBeNull(); |
| }); |
| |
| it('returns no kernel for empty set', () => { |
| const messageSet = MessageSet.createEmpty(); |
| expect(messageSet.getMessageAccessorOrNull(12345)).toBeNull(); |
| }); |
| |
| it('returns message that has been set', () => { |
| const messageSet = MessageSet.createEmpty(); |
| const message = TestMessage.createEmpty(); |
| messageSet.setMessage(12345, message); |
| expect(messageSet.getMessageOrNull(12345, TestMessage.instanceCreator)) |
| .toBe(message); |
| }); |
| |
| it('returns null for cleared message', () => { |
| const messageSet = MessageSet.createEmpty(); |
| const message = TestMessage.createEmpty(); |
| messageSet.setMessage(12345, message); |
| messageSet.clearMessage(12345); |
| expect(messageSet.getMessageAccessorOrNull(12345)).toBeNull(); |
| }); |
| |
| it('returns false for not present message', () => { |
| const messageSet = MessageSet.createEmpty(); |
| expect(messageSet.hasMessage(12345)).toBe(false); |
| }); |
| |
| it('returns true for present message', () => { |
| const messageSet = MessageSet.createEmpty(); |
| const message = TestMessage.createEmpty(); |
| messageSet.setMessage(12345, message); |
| expect(messageSet.hasMessage(12345)).toBe(true); |
| }); |
| |
| it('returns false for cleared message', () => { |
| const messageSet = MessageSet.createEmpty(); |
| const message = TestMessage.createEmpty(); |
| messageSet.setMessage(12345, message); |
| messageSet.clearMessage(12345); |
| expect(messageSet.hasMessage(12345)).toBe(false); |
| }); |
| |
| it('returns false for cleared message without it being present', () => { |
| const messageSet = MessageSet.createEmpty(); |
| messageSet.clearMessage(12345); |
| expect(messageSet.hasMessage(12345)).toBe(false); |
| }); |
| |
| const createMessageSet = () => { |
| const messageSet = MessageSet.createEmpty(); |
| const message = TestMessage.createEmpty(); |
| message.setInt32(1, 2); |
| messageSet.setMessage(12345, message); |
| |
| |
| const parsedKernel = |
| Kernel.fromArrayBuffer(messageSet.internalGetKernel().serialize()); |
| return MessageSet.fromKernel(parsedKernel); |
| }; |
| |
| it('pass through pivot for getMessageOrNull', () => { |
| const messageSet = createMessageSet(); |
| const message = |
| messageSet.getMessageOrNull(12345, TestMessage.instanceCreator, 2); |
| expect(message.internalGetKernel().getPivot()).toBe(2); |
| }); |
| |
| it('pass through pivot for getMessageAttach', () => { |
| const messageSet = createMessageSet(); |
| const message = |
| messageSet.getMessageAttach(12345, TestMessage.instanceCreator, 2); |
| expect(message.internalGetKernel().getPivot()).toBe(2); |
| }); |
| |
| it('pass through pivot for getMessageAccessorOrNull', () => { |
| const messageSet = createMessageSet(); |
| const kernel = messageSet.getMessageAccessorOrNull(12345, 2); |
| expect(kernel.getPivot()).toBe(2); |
| }); |
| |
| it('pick the last value in the stream', () => { |
| const arrayBuffer = createArrayBuffer( |
| 0x52, // Tag (field:10, length delimited) |
| 0x14, // Length of 20 bytes |
| 0x0B, // Start group fieldnumber 1 |
| 0x10, // Tag (field 2, varint) |
| 0xB9, // 12345 |
| 0x60, // 12345 |
| 0x1A, // Tag (field 3, length delimited) |
| 0x03, // length 3 |
| 0xA0, // Tag (fieldnumber 20, varint) |
| 0x01, // Tag (fieldnumber 20, varint) |
| 0x1E, // 30 |
| 0x0C, // Stop Group field number 1 |
| // second group |
| 0x0B, // Start group fieldnumber 1 |
| 0x10, // Tag (field 2, varint) |
| 0xB9, // 12345 |
| 0x60, // 12345 |
| 0x1A, // Tag (field 3, length delimited) |
| 0x03, // length 3 |
| 0xA0, // Tag (fieldnumber 20, varint) |
| 0x01, // Tag (fieldnumber 20, varint) |
| 0x01, // 1 |
| 0x0C // Stop Group field number 1 |
| ); |
| |
| const outerMessage = Kernel.fromArrayBuffer(arrayBuffer); |
| |
| const messageSet = outerMessage.getMessage(10, MessageSet.fromKernel); |
| |
| const message = |
| messageSet.getMessageOrNull(12345, TestMessage.instanceCreator); |
| expect(message.getInt32WithDefault(20)).toBe(1); |
| }); |
| |
| it('removes duplicates when read', () => { |
| const arrayBuffer = createArrayBuffer( |
| 0x52, // Tag (field:10, length delimited) |
| 0x14, // Length of 20 bytes |
| 0x0B, // Start group fieldnumber 1 |
| 0x10, // Tag (field 2, varint) |
| 0xB9, // 12345 |
| 0x60, // 12345 |
| 0x1A, // Tag (field 3, length delimited) |
| 0x03, // length 3 |
| 0xA0, // Tag (fieldnumber 20, varint) |
| 0x01, // Tag (fieldnumber 20, varint) |
| 0x1E, // 30 |
| 0x0C, // Stop Group field number 1 |
| // second group |
| 0x0B, // Start group fieldnumber 1 |
| 0x10, // Tag (field 2, varint) |
| 0xB9, // 12345 |
| 0x60, // 12345 |
| 0x1A, // Tag (field 3, length delimited) |
| 0x03, // length 3 |
| 0xA0, // Tag (fieldnumber 20, varint) |
| 0x01, // Tag (fieldnumber 20, varint) |
| 0x01, // 1 |
| 0x0C // Stop Group field number 1 |
| ); |
| |
| |
| const outerMessage = Kernel.fromArrayBuffer(arrayBuffer); |
| outerMessage.getMessageAttach(10, MessageSet.fromKernel); |
| |
| expect(outerMessage.serialize()) |
| .toEqual(createArrayBuffer( |
| 0x52, // Tag (field:10, length delimited) |
| 0x0A, // Length of 10 bytes |
| 0x0B, // Start group fieldnumber 1 |
| 0x10, // Tag (field 2, varint) |
| 0xB9, // 12345 |
| 0x60, // 12345 |
| 0x1A, // Tag (field 3, length delimited) |
| 0x03, // length 3 |
| 0xA0, // Tag (fieldnumber 20, varint) |
| 0x01, // Tag (fieldnumber 20, varint) |
| 0x01, // 1 |
| 0x0C // Stop Group field number 1 |
| )); |
| }); |
| |
| it('allow for large typeIds', () => { |
| const messageSet = MessageSet.createEmpty(); |
| const message = TestMessage.createEmpty(); |
| messageSet.setMessage(0xFFFFFFFE >>> 0, message); |
| expect(messageSet.hasMessage(0xFFFFFFFE >>> 0)).toBe(true); |
| }); |
| }); |
| |
| describe('Optional MessageSet does', () => { |
| // message Bar { |
| // optional MessageSet mset = 10; |
| //} |
| // |
| // message Foo { |
| // extend proto2.bridge.MessageSet { |
| // optional Foo message_set_extension = 12345; |
| // } |
| // optional int32 f20 = 20; |
| //} |
| |
| it('encode as a field', () => { |
| const fooMessage = Kernel.createEmpty(); |
| fooMessage.setInt32(20, 30); |
| |
| const messageSet = MessageSet.createEmpty(); |
| messageSet.setMessage(12345, TestMessage.instanceCreator(fooMessage)); |
| |
| const barMessage = Kernel.createEmpty(); |
| barMessage.setMessage(10, messageSet); |
| |
| expect(barMessage.serialize()) |
| .toEqual(createArrayBuffer( |
| 0x52, // Tag (field:10, length delimited) |
| 0x0A, // Length of 10 bytes |
| 0x0B, // Start group fieldnumber 1 |
| 0x10, // Tag (field 2, varint) |
| 0xB9, // 12345 |
| 0x60, // 12345 |
| 0x1A, // Tag (field 3, length delimited) |
| 0x03, // length 3 |
| 0xA0, // Tag (fieldnumber 20, varint) |
| 0x01, // Tag (fieldnumber 20, varint) |
| 0x1E, // 30 |
| 0x0C // Stop Group field number 1 |
| )); |
| }); |
| |
| it('deserializes', () => { |
| const fooMessage = Kernel.createEmpty(); |
| fooMessage.setInt32(20, 30); |
| |
| const messageSet = MessageSet.createEmpty(); |
| messageSet.setMessage(12345, TestMessage.instanceCreator(fooMessage)); |
| |
| |
| const barMessage = Kernel.createEmpty(); |
| barMessage.setMessage(10, messageSet); |
| |
| const arrayBuffer = barMessage.serialize(); |
| |
| const barMessageParsed = Kernel.fromArrayBuffer(arrayBuffer); |
| expect(barMessageParsed.hasFieldNumber(10)).toBe(true); |
| |
| const messageSetParsed = |
| barMessageParsed.getMessage(10, MessageSet.fromKernel); |
| |
| const fooMessageParsed = |
| messageSetParsed.getMessageOrNull(12345, TestMessage.instanceCreator) |
| .internalGetKernel(); |
| |
| expect(fooMessageParsed.getInt32WithDefault(20)).toBe(30); |
| }); |
| }); |