bin-protocol
Version:
buffer maker and parser for binary protocols
328 lines (265 loc) • 11.3 kB
JavaScript
'use strict';
/* global describe, it, expect */
var Protocol = require('../lib/index');
var fs = require('fs');
var path = require('path');
var Long = require('long');
var createProtocol = function (file, options) {
return Protocol.createProtobufProtocol(fs.readFileSync(path.join(__dirname, file)), options);
};
var BasicProtocol = createProtocol('proto/basic.proto');
var BasicNoTypeSpecificDefaultsProtocol = createProtocol('proto/basic.proto', { typeSpecificDefaults: false });
var ComplexProtocol = createProtocol('proto/complex.proto');
var DefaultsRequiredProtocol = createProtocol('proto/defaults-required.proto');
var DefaultsOptionalProtocol = createProtocol('proto/defaults-optional.proto');
var DefaultsMiscProtocol = createProtocol('proto/defaults-misc.proto');
var NoPackageProtocol = createProtocol('proto/no-package.proto');
var RequiredNoDefaultsProtocol = createProtocol('proto/required-no-defaults.proto');
var RepeatedPackedProtocol = createProtocol('proto/packed.proto');
var RepeatedMessageProtocol = createProtocol('proto/repeated-message.proto');
var OneofProtocol = createProtocol('proto/oneof.proto');
var MapProtocol = createProtocol('proto/map.proto');
describe('Protobuf', function () {
it('should parse/build basic types', function () {
var protocol = new BasicProtocol();
var obj = {
int32 : 1,
uint32 : 2,
sint32 : 3,
bool : true,
int64 : Long.fromNumber(4),
uint64 : Long.fromNumber(5, true),
sint64 : Long.fromNumber(6),
fixed64 : Long.fromNumber(7, true),
sfixed64 : Long.fromNumber(8),
double : 9,
fixed32 : 10,
sfixed32 : 11,
float : 12,
bytes : new Buffer('abcde'),
string : 'Hello',
myenum : 2,
strings : ['qwe', 'asd']
};
var buffer = new Buffer([8, 1, 16, 2, 24, 6, 32, 1, 40, 4, 48, 5, 56, 12, 65, 7, 0, 0, 0, 0, 0, 0,
0, 73, 8, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 34, 64, 93, 10, 0, 0, 0, 101, 11,
0, 0, 0, 109, 0, 0, 64, 65, 114, 5, 97, 98, 99, 100, 101, 122, 5, 72, 101, 108, 108, 111,
128, 1, 2, 138, 1, 3, 113, 119, 101, 138, 1, 3, 97, 115, 100]);
var encoded = protocol.write().basic.Test(obj).result;
encoded.should.be.eql(buffer);
protocol.read(encoded).basic.Test().result.should.be.eql(obj);
});
it('should parse/build complex embedded messages', function () {
var protocol = new ComplexProtocol();
var obj = {
model: 'Rusty',
vendor: {
name: 'Iron Inc.',
address: {
country: 'US'
},
models: []
},
speed: 2
};
var buffer = new Buffer([10, 5, 82, 117, 115, 116, 121, 18, 17, 10, 9, 73, 114, 111, 110, 32, 73, 110, 99, 46, 18, 4, 10, 2, 85, 83, 24, 2]);
var encoded = protocol.write().Game.Cars.Car(obj).result;
encoded.should.be.eql(buffer);
protocol.read(encoded).Game.Cars.Car().result.should.be.eql(obj);
});
it('should parse/build embedded messages with referenced field types', function () {
var protocol = new ComplexProtocol();
var obj = {
first_name: 'John',
last_name: 'Doe',
address: {
country: 'US'
}
};
var buffer = new Buffer([10, 4, 74, 111, 104, 110, 18, 3, 68, 111, 101, 26, 4, 10, 2, 85, 83]);
var encoded = protocol.write().Game.Cars.Car.Holder(obj).result;
encoded.should.be.eql(buffer);
protocol.read(encoded).Game.Cars.Car.Holder().result.should.be.eql(obj);
});
it('reader should throw on unknown message tag', function () {
var protocol = new BasicProtocol();
var buffer = new Buffer([144, 1, 1]);
function f() {
protocol.read(buffer).basic.Test();
}
expect(f).to.throw('Unknown message tag');
});
it('writer should use default option with required fields', function () {
var protocol = new DefaultsRequiredProtocol();
var buffer = new Buffer([8, 133, 255, 255, 255, 255, 255, 255, 255, 255, 1, 16, 123, 24,
245, 1, 32, 0, 40, 133, 255, 255, 255, 255, 255, 255, 255, 255, 1, 48, 123, 56, 245,
1, 65, 123, 0, 0, 0, 0, 0, 0, 0, 73, 133, 255, 255, 255, 255, 255, 255, 255, 81, 102,
102, 102, 102, 102, 198, 94, 64, 93, 123, 0, 0, 0, 101, 133, 255, 255, 255, 109, 0, 0,
246, 66, 114, 3, 113, 119, 101, 122, 3, 97, 115, 100, 128, 1, 2]);
protocol.write().basic.Test({}).result.should.be.eql(buffer);
});
it('writer should not use default option with optional fields', function () {
var protocol = new DefaultsOptionalProtocol();
protocol.write().basic.Test({}).result.should.be.eql(new Buffer(0));
});
it('writer should throw on missing required field', function () {
var protocol = new RequiredNoDefaultsProtocol();
function f() {
protocol.write().basic.Test({});
}
expect(f).to.throw('Missing required field basic.Test:int32');
});
it('reader should use default option with optional fields', function () {
var protocol = new DefaultsOptionalProtocol();
protocol.read(new Buffer(0)).basic.Test().result.should.be.eql({
int32 : -123,
uint32 : 123,
sint32 : -123,
bool : false,
int64 : Long.fromNumber(-123),
uint64 : Long.fromNumber(123, true),
sint64 : Long.fromNumber(-123),
fixed64 : Long.fromNumber(123, true),
sfixed64 : Long.fromNumber(-123),
double : 123.1,
fixed32 : 123,
sfixed32 : -123,
float : 123,
bytes : new Buffer('qwe'),
string : 'asd',
myenum : 2
});
});
it('reader should use default option with required fields', function () {
var protocol = new DefaultsRequiredProtocol();
var encoded = protocol.write().basic.Test({}).result;
protocol.read(encoded).basic.Test().result.should.be.eql({
int32 : -123,
uint32 : 123,
sint32 : -123,
bool : false,
int64 : Long.fromNumber(-123),
uint64 : Long.fromNumber(123, true),
sint64 : Long.fromNumber(-123),
fixed64 : Long.fromNumber(123, true),
sfixed64 : Long.fromNumber(-123),
double : 123.1,
fixed32 : 123,
sfixed32 : -123,
float : 123,
bytes : new Buffer('qwe'),
string : 'asd',
myenum : 2
});
});
it('reader should use type-specific default value with optional fields', function () {
var protocol = new BasicProtocol();
protocol.read(new Buffer(0)).basic.Test().result.should.be.eql({
int32 : 0,
uint32 : 0,
sint32 : 0,
bool : false,
int64 : Long.ZERO,
uint64 : Long.UZERO,
sint64 : Long.ZERO,
fixed64 : Long.UZERO,
sfixed64 : Long.ZERO,
double : 0,
fixed32 : 0,
sfixed32 : 0,
float : 0,
bytes : new Buffer(0),
string : '',
myenum : 1,
strings : []
});
});
it('reader should not use type-specific default value with optional fields when typeSpecificDefaults is set', function () {
var protocol = new BasicNoTypeSpecificDefaultsProtocol();
protocol.read(new Buffer(0)).basic.Test().result.should.be.eql({});
});
it('reader should throw on missing required field', function () {
var protocol = new RequiredNoDefaultsProtocol();
function f() {
protocol.read(new Buffer(0)).basic.Test({});
}
expect(f).to.throw('Missing required field basic.Test:int32');
});
it('handle misc default options', function () {
var protocol = new DefaultsMiscProtocol();
protocol.read(new Buffer(0)).basic.Test().result.should.be.eql({
string1: 'asd',
string2: 'asd',
string3: 'asd',
test: null
});
});
it('proto file without package', function () {
var protocol = new NoPackageProtocol();
var encoded = protocol.write().Test({
string: 'yo',
test2: {
string: 'hi'
}
}).result;
protocol.read(encoded).Test().result.should.be.eql({
string: 'yo',
myenum: 1,
myenum2: 1,
test2: {
string: 'hi'
}
});
});
it('repeated packed = true', function () {
var protocol = new RepeatedPackedProtocol();
var encoded = protocol.write().packed.Test({
nums: [3, 270, 86942]
}).result;
encoded.should.be.eql(new Buffer([0x22, 0x06, 0x03, 0x8e, 0x02, 0x9E, 0xA7, 0x05]));
protocol.read(encoded).packed.Test().result.should.be.eql({
nums: [3, 270, 86942]
});
});
it('repeated embedded message', function () {
var protocol = new RepeatedMessageProtocol();
var user = {
name: 'John Doe',
addresses: [
{ country: 'US' },
{ country: 'UA' }
]
};
var encoded = protocol.write().UserDatabase.User(user).result;
encoded.should.be.eql(new Buffer([10, 8, 74, 111, 104, 110, 32, 68, 111, 101, 18, 4, 10, 2, 85, 83, 18, 4, 10, 2, 85, 65]));
protocol.read(encoded).UserDatabase.User().result.should.be.eql(user);
});
it('oneof message', function () {
var protocol = new OneofProtocol();
var encoded = protocol.write().SampleMessage({
name1: 'John Doe',
id1: 12,
name2: 'John Smith',
id2: 21,
}).result;
protocol.read(encoded).SampleMessage().result.should.be.eql({
name1: 'John Doe',
id1: 0,
name2: 'John Smith',
id2: 0
});
});
it('map message', function () {
var protocol = new MapProtocol();
var msg = {
items: {
id1: 'description1',
id2: 'description2',
}
};
var encoded = protocol.write().map.TODO(msg).result;
encoded.should.be.eql(new Buffer([10, 19, 10, 3, 105, 100, 49, 18, 12, 100, 101, 115, 99, 114, 105,
112, 116, 105, 111, 110, 49, 10, 19, 10, 3, 105, 100, 50, 18, 12, 100, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 50]));
protocol.read(encoded).map.TODO().result.should.be.eql(msg);
});
});