flocore-p2p/test/messages/index.js
2015-10-16 14:59:05 -04:00

217 lines
7.4 KiB
JavaScript

'use strict';
var chai = require('chai');
var should = chai.should();
var Buffers = require('buffers');
var P2P = require('../../');
var Messages = P2P.Messages;
var messages = new Messages();
var bitcore = require('bitcore-lib');
var Data = require('../data/messages'); //todo merge with commandData
var commandData = require('../data/messages.json');
function getPayloadBuffer(messageBuffer) {
return new Buffer(messageBuffer.slice(48), 'hex');
}
describe('Messages', function() {
var buildMessage = function(hex) {
var m = Buffers();
m.push(new Buffer(hex, 'hex'));
return m;
};
describe('@constructor', function() {
it('sets properties correctly', function() {
var network = bitcore.Networks.defaultNetwork;
var messages = new Messages({
network: network,
Block: bitcore.Block,
Transaction: bitcore.Transaction
});
should.exist(messages.builder.commands);
should.exist(messages.builder.constructors);
messages.builder.constructors.Block.should.equal(bitcore.Block);
messages.builder.constructors.Transaction.should.equal(bitcore.Transaction);
messages.network.should.deep.equal(network);
});
it('network should be unique for each set of messages', function() {
var messages = new Messages({
network: bitcore.Networks.livenet
});
var messages2 = new Messages({
network: bitcore.Networks.testnet
});
messages.network.should.deep.equal(bitcore.Networks.livenet);
messages2.network.should.deep.equal(bitcore.Networks.testnet);
var message1 = messages.Version();
message1.network.should.deep.equal(bitcore.Networks.livenet);
var message2 = messages2.Version();
message2.network.should.deep.equal(bitcore.Networks.testnet);
});
});
describe('@constructor for all command messages', function() {
var messages = new Messages();
Object.keys(messages.builder.commandsMap).forEach(function(command) {
var name = messages.builder.commandsMap[command];
it('message.' + name, function(done) {
should.exist(messages[name]);
var message = messages[name]();
should.exist(message);
message.should.be.instanceof(messages[name]._constructor);
done();
});
});
});
describe('#fromBuffer/#toBuffer round trip for all commands', function() {
var messages = new Messages();
Object.keys(messages.builder.commandsMap).forEach(function(command) {
var name = messages.builder.commandsMap[command];
it(name, function(done) {
var payloadBuffer = getPayloadBuffer(commandData[command].message);
should.exist(messages[name]);
var message = messages[name].fromBuffer(payloadBuffer);
var outputBuffer = message.getPayload();
outputBuffer.toString('hex').should.equal(payloadBuffer.toString('hex'));
outputBuffer.should.deep.equal(payloadBuffer);
var expectedBuffer = new Buffer(commandData[command].message, 'hex');
message.toBuffer().should.deep.equal(expectedBuffer);
done();
});
});
});
describe('Default Network', function() {
var messages = new Messages();
Object.keys(messages.builder.commandsMap).forEach(function(command) {
var name = messages.builder.commandsMap[command];
it(name, function() {
var message = messages[name]();
message.network.should.deep.equal(bitcore.Networks.defaultNetwork);
});
});
});
describe('messages.Version', function() {
var messages = new Messages();
it('#fromBuffer works w/o fRelay arg', function() {
var payloadBuffer = getPayloadBuffer(Data.version.messagenofrelay);
var message = messages.Version.fromBuffer(payloadBuffer);
message.relay.should.equal(true);
});
it('#relay setting works', function() {
[true, false].forEach(function(relay) {
var message = messages.Version({
relay: relay
});
message.relay.should.equal(relay);
var messageBuf = message.getPayload();
var newMessage = messages.Version.fromBuffer(messageBuf);
newMessage.relay.should.equal(relay);
});
});
});
describe('Inventory Helpers', function() {
var messages = new Messages();
var constructors = messages.builder.inventoryCommands;
var fakeHash = 'e2dfb8afe1575bfacae1a0b4afc49af7ddda69285857267bae0e22be15f74a3a';
describe('#forTransaction', function() {
constructors.forEach(function(command) {
var name = messages.builder.commandsMap[command];
it(name, function() {
should.exist(messages[name].forTransaction);
var message = messages[name].forTransaction(fakeHash);
should.exist(message);
message.should.be.instanceof(messages[name]._constructor);
});
});
});
describe('#forBlock', function() {
constructors.forEach(function(command) {
var name = messages.builder.commandsMap[command];
it(name, function() {
var message = messages[name].forBlock(fakeHash);
should.exist(message);
message.should.be.instanceof(messages[name]._constructor);
});
});
});
describe('#forFilteredBlock', function() {
constructors.forEach(function(command) {
var name = messages.builder.commandsMap[command];
it(name, function() {
var message = messages[name].forFilteredBlock(fakeHash);
should.exist(message);
message.should.be.instanceof(messages[name]._constructor);
});
});
});
});
describe('#parseBuffer', function() {
it('fails with invalid command', function() {
var invalidCommand = 'f9beb4d96d616c6963696f757300000025000000bd5e830c' +
'0102000000ec3995c1bf7269ff728818a65e53af00cbbee6b6eca8ac9ce7bc79d87' +
'7041ed8';
var fails = function() {
var bufs = buildMessage(invalidCommand);
messages.parseBuffer(bufs);
};
fails.should.throw('Unsupported message command: malicious');
});
it('ignores malformed messages', function() {
var malformed1 = 'd8c4c3d976657273696f6e000000000065000000fc970f1772110' +
'1000100000000000000ba6288540000000001000000000000000000000000000000' +
'0000ffffba8886dceab0010000000000000000000000000000000000ffff0509552' +
'2208de7e1c1ef80a1cea70f2f5361746f7368693a302e392e312fa317050001';
var malformed2 = 'f9beb4d967657464617461000000000089000000d88134740102' +
'0000006308e4a380c949dbad182747b0f7b6a89e874328ca41f37287f74a81b8f84' +
'86d';
var malformed3 = 'f9beb4d967657464617461000000000025000000616263640102' +
'00000069ebcbc34a4f9890da9aea0f773beba883a9afb1ab9ad7647dd4a1cd346c3' +
'728';
[malformed1, malformed2, malformed3].forEach(function(malformed) {
var ret = messages.parseBuffer(buildMessage(malformed));
should.not.exist(ret);
});
});
});
describe('#add', function() {
it('should add a custom message', function() {
var network = bitcore.Networks.defaultNetwork;
var messages = new Messages({
network: network,
Block: bitcore.Block,
Transaction: bitcore.Transaction
});
var CustomMessage = function(arg, options) {
this.arg = arg;
};
messages.add('custom', 'Custom', CustomMessage);
should.exist(messages.Custom);
var message = messages.Custom('hello');
message.arg.should.equal('hello');
});
});
});