flocore-p2p/test/pool.js
Braydon Fuller 11bee8b900 Improved API:
- Renamed "Commands" to "builder"
- "Messages.parseMessage" to "Messages.parseBuffer"
- Changed to use private methods for "discardUntilNextMessage" and "buildFromBuffer"
- Cleaned up tests
2015-03-11 23:57:08 -04:00

297 lines
7.4 KiB
JavaScript

'use strict';
var chai = require('chai');
/* jshint unused: false */
var should = chai.should();
var expect = chai.expect;
var bitcore = require('bitcore');
var P2P = require('../');
var Peer = P2P.Peer;
var MessagesData = require('./data/messages');
var Messages = P2P.Messages;
var messages = new Messages();
var Pool = P2P.Pool;
var Networks = bitcore.Networks;
var dns = require('dns');
var sinon = require('sinon');
function getPayloadBuffer(messageBuffer) {
return new Buffer(messageBuffer.slice(48), 'hex');
}
describe('Pool', function() {
it('create instance', function() {
var pool = new Pool();
should.exist(pool.network);
expect(pool.network).to.satisfy(function(network) {
return network === Networks.testnet || network === Networks.livenet;
});
});
it('create instance setting the network', function() {
var pool = new Pool({network: Networks.testnet});
pool.network.should.equal(Networks.testnet);
});
it('discover peers via dns', function() {
var stub = sinon.stub(dns, 'resolve', function(seed, callback) {
callback(null, ['10.10.10.1', '10.10.10.2', '10.10.10.3']);
});
var pool = new Pool({network: Networks.livenet});
pool.connect();
pool.disconnect();
pool._addrs.length.should.equal(3);
stub.restore();
});
it('optionally connect without dns seeds', function() {
var stub = sinon.stub(dns, 'resolve', function(seed, callback) {
throw new Error('DNS should not be called');
});
var options = {
network: Networks.livenet,
dnsSeed: false,
maxSize: 1,
addrs: [
{
ip: {
v4: 'localhost'
}
},
{
ip: {
v4: 'localhost2'
}
}
]
};
var pool = new Pool(options);
pool.connect();
pool.disconnect();
pool._addrs.length.should.equal(2);
stub.restore();
});
it('will add addrs via options argument', function() {
var options = {
network: Networks.livenet,
dnsSeed: false,
addrs: [
{
ip: {
v4: 'localhost'
}
}
]
};
var pool = new Pool(options);
pool._addrs.length.should.equal(1);
});
it('add new addrs as they are announced over the network', function(done) {
// only emit an event, no need to connect
var peerConnectStub = sinon.stub(Peer.prototype, 'connect', function() {
this._readMessage();
this.emit('ready');
});
// mock a addr peer event
var peerMessageStub = sinon.stub(Peer.prototype, '_readMessage', function() {
var payloadBuffer = getPayloadBuffer(MessagesData.addr.message);
var message = messages._buildFromBuffer('addr', payloadBuffer);
this.emit(message.command, message);
});
var options = {
network: Networks.testnet,
dnsSeed: false,
addrs: [
{
ip: {
v4: 'localhost'
}
}
]
};
var pool = new Pool(options);
// listen for the event
pool.on('peeraddr', function(peer, message) {
pool._addrs.length.should.equal(502);
// restore stubs
peerConnectStub.restore();
peerMessageStub.restore();
for (var i = 0; i < pool._addrs.length; i++) {
should.exist(pool._addrs[i].hash);
should.exist(pool._addrs[i].ip);
should.exist(pool._addrs[i].ip.v4);
}
// done
done();
});
pool.connect();
});
it('can optionally not listen to new addrs messages', function(done) {
// only emit an event, no need to connect
var peerConnectStub = sinon.stub(Peer.prototype, 'connect', function() {
this._readMessage();
this.emit('ready');
});
// mock a addr peer event
var peerMessageStub = sinon.stub(Peer.prototype, '_readMessage', function() {
var payloadBuffer = getPayloadBuffer(MessagesData.addr.message);
var message = messages._buildFromBuffer('addr', payloadBuffer);
this.emit(message.command, message);
});
var options = {
network: Networks.testnet,
dnsSeed: false,
listenAddr: false,
addrs: [
{
ip: {
v4: 'localhost'
}
}
]
};
var pool = new Pool(options);
// listen for the event
pool.on('peeraddr', function(peer, message) {
pool._addrs.length.should.equal(1);
// restore stubs
peerConnectStub.restore();
peerMessageStub.restore();
for (var i = 0; i < pool._addrs.length; i++) {
should.exist(pool._addrs[i].hash);
should.exist(pool._addrs[i].ip);
should.exist(pool._addrs[i].ip.v4);
}
// done
done();
});
pool.connect();
});
it('propagate connect, ready, and disconnect peer events', function(done) {
var peerConnectStub = sinon.stub(Peer.prototype, 'connect', function() {
this.emit('connect', this, {});
this.emit('ready');
});
var peerDisconnectStub = sinon.stub(Peer.prototype, 'disconnect', function() {
this.emit('disconnect', this, {});
});
var poolRemoveStub = sinon.stub(Pool.prototype, '_removeConnectedPeer', function() {});
var pool = new Pool({
dnsSeed: false,
addrs: [
{
ip: {
v4: 'localhost'
}
}
]
});
var poolDisconnectStub;
pool.on('peerconnect', function(peer, addr) {
pool.on('peerready', function(peer, addr) {
// disconnect when the peer is ready
poolDisconnectStub = sinon.stub(Pool.prototype, 'disconnect', function() {
peer.disconnect();
});
pool.disconnect();
});
});
pool.on('peerdisconnect', function(peer, addr) {
// Restore stubs
peerConnectStub.restore();
peerDisconnectStub.restore();
poolDisconnectStub.restore();
poolRemoveStub.restore();
// done
done();
});
pool.connect();
});
it('propagate relay property to peers', function(done) {
var count = 0;
var peerConnectStub = sinon.stub(Peer.prototype, 'connect', function() {
this.emit('connect', this, {});
});
[true, false].forEach(function(relay) {
var pool = new Pool({relay: relay, dnsSeed: false});
pool._addAddr({ ip: { v4: 'localhost' } });
pool.on('peerconnect', function(peer, addr) {
peer.relay.should.equal(relay);
pool.disconnect();
if(++count == 2) {
done();
}
});
pool.connect();
});
peerConnectStub.restore();
});
it('output the console correctly', function() {
var pool = new Pool();
pool.inspect().should.equal('<Pool network: livenet, connected: 0, available: 0>');
});
it('emit seederrors with error', function(done) {
var dnsStub = sinon.stub(dns, 'resolve', function(seed, callback) {
callback(new Error('A DNS error'));
});
var pool = new Pool({network: Networks.livenet, maxSize: 1});
pool.once('seederror', function(error) {
should.exist(error);
pool.disconnect();
dnsStub.restore();
done();
});
pool.connect();
});
it('emit seederrors with notfound', function(done) {
var dnsStub = sinon.stub(dns, 'resolve', function(seed, callback) {
callback(null, []);
});
var pool = new Pool({network: Networks.livenet, maxSize: 1});
pool.once('seederror', function(error) {
should.exist(error);
pool.disconnect();
dnsStub.restore();
done();
});
pool.connect();
});
});