263 lines
8.5 KiB
JavaScript
263 lines
8.5 KiB
JavaScript
|
/**
|
||
|
* @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);
|
||
|
});
|
||
|
});
|