Address: Added unit tests for new mempool index methods
This commit is contained in:
parent
89ef28f0b7
commit
5ac3b1c61f
@ -7,6 +7,8 @@ var bitcorenode = require('../../../');
|
||||
var AddressService = bitcorenode.services.Address;
|
||||
var blockData = require('../../data/livenet-345003.json');
|
||||
var bitcore = require('bitcore-lib');
|
||||
var memdown = require('memdown');
|
||||
var leveldown = require('leveldown');
|
||||
var Script = bitcore.Script;
|
||||
var Address = bitcore.Address;
|
||||
var Networks = bitcore.Networks;
|
||||
@ -31,6 +33,258 @@ var mocknode = {
|
||||
|
||||
describe('Address Service', function() {
|
||||
var txBuf = new Buffer(txData[0], 'hex');
|
||||
|
||||
describe('@constructor', function() {
|
||||
it('config to use memdown for mempool index', function() {
|
||||
var am = new AddressService({
|
||||
mempoolMemoryIndex: true,
|
||||
node: mocknode
|
||||
});
|
||||
am.levelupStore.should.equal(memdown);
|
||||
});
|
||||
it('config to use leveldown for mempool index', function() {
|
||||
var am = new AddressService({
|
||||
node: mocknode
|
||||
});
|
||||
am.levelupStore.should.equal(leveldown);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#start', function() {
|
||||
it('will flush existing mempool', function(done) {
|
||||
var leveldownmock = {
|
||||
destroy: sinon.stub().callsArgWith(1, null)
|
||||
};
|
||||
var TestAddressService = proxyquire('../../../lib/services/address', {
|
||||
'fs': {
|
||||
existsSync: sinon.stub().returns(true)
|
||||
},
|
||||
'leveldown': leveldownmock,
|
||||
'levelup': sinon.stub().callsArgWith(2, null),
|
||||
'mkdirp': sinon.stub().callsArgWith(1, null)
|
||||
});
|
||||
var am = new TestAddressService({
|
||||
mempoolMemoryIndex: true,
|
||||
node: mocknode
|
||||
});
|
||||
am.start(function() {
|
||||
leveldownmock.destroy.callCount.should.equal(1);
|
||||
leveldownmock.destroy.args[0][0].should.equal('testdir/testnet3/bitcore-addressmempool.db');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('will mkdirp if directory does not exist', function(done) {
|
||||
var leveldownmock = {
|
||||
destroy: sinon.stub().callsArgWith(1, null)
|
||||
};
|
||||
var mkdirpmock = sinon.stub().callsArgWith(1, null);
|
||||
var TestAddressService = proxyquire('../../../lib/services/address', {
|
||||
'fs': {
|
||||
existsSync: sinon.stub().returns(false)
|
||||
},
|
||||
'leveldown': leveldownmock,
|
||||
'levelup': sinon.stub().callsArgWith(2, null),
|
||||
'mkdirp': mkdirpmock
|
||||
});
|
||||
var am = new TestAddressService({
|
||||
mempoolMemoryIndex: true,
|
||||
node: mocknode
|
||||
});
|
||||
am.start(function() {
|
||||
mkdirpmock.callCount.should.equal(1);
|
||||
mkdirpmock.args[0][0].should.equal('testdir/testnet3/bitcore-addressmempool.db');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('start levelup db for mempool index', function(done) {
|
||||
var TestAddressService = proxyquire('../../../lib/services/address', {
|
||||
'fs': {
|
||||
existsSync: sinon.stub().returns(true)
|
||||
},
|
||||
'leveldown': {
|
||||
destroy: sinon.stub().callsArgWith(1, null)
|
||||
},
|
||||
'levelup': function(dbPath, options, callback) {
|
||||
dbPath.should.equal('testdir/testnet3/bitcore-addressmempool.db');
|
||||
options.db.should.equal(memdown);
|
||||
options.keyEncoding.should.equal('binary');
|
||||
options.valueEncoding.should.equal('binary');
|
||||
options.fillCache.should.equal(false);
|
||||
setImmediate(callback);
|
||||
},
|
||||
'mkdirp': sinon.stub().callsArgWith(1, null)
|
||||
});
|
||||
var am = new TestAddressService({
|
||||
mempoolMemoryIndex: true,
|
||||
node: mocknode
|
||||
});
|
||||
am.start(function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('handle error from mkdirp', function(done) {
|
||||
var TestAddressService = proxyquire('../../../lib/services/address', {
|
||||
'fs': {
|
||||
existsSync: sinon.stub().returns(false)
|
||||
},
|
||||
'leveldown': {
|
||||
destroy: sinon.stub().callsArgWith(1, null)
|
||||
},
|
||||
'levelup': sinon.stub().callsArgWith(2, null),
|
||||
'mkdirp': sinon.stub().callsArgWith(1, new Error('testerror'))
|
||||
});
|
||||
var am = new TestAddressService({
|
||||
mempoolMemoryIndex: true,
|
||||
node: mocknode
|
||||
});
|
||||
am.start(function(err) {
|
||||
err.message.should.equal('testerror');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('handle error from levelup', function(done) {
|
||||
var TestAddressService = proxyquire('../../../lib/services/address', {
|
||||
'fs': {
|
||||
existsSync: sinon.stub().returns(false)
|
||||
},
|
||||
'leveldown': {
|
||||
destroy: sinon.stub().callsArgWith(1, null)
|
||||
},
|
||||
'levelup': sinon.stub().callsArgWith(2, new Error('leveltesterror')),
|
||||
'mkdirp': sinon.stub().callsArgWith(1, null)
|
||||
});
|
||||
var am = new TestAddressService({
|
||||
mempoolMemoryIndex: true,
|
||||
node: mocknode
|
||||
});
|
||||
am.start(function(err) {
|
||||
err.message.should.equal('leveltesterror');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('handle error from leveldown.destroy', function(done) {
|
||||
var TestAddressService = proxyquire('../../../lib/services/address', {
|
||||
'fs': {
|
||||
existsSync: sinon.stub().returns(true)
|
||||
},
|
||||
'leveldown': {
|
||||
destroy: sinon.stub().callsArgWith(1, new Error('destroy'))
|
||||
},
|
||||
'levelup': sinon.stub().callsArgWith(2, null),
|
||||
'mkdirp': sinon.stub().callsArgWith(1, null)
|
||||
});
|
||||
var am = new TestAddressService({
|
||||
mempoolMemoryIndex: true,
|
||||
node: mocknode
|
||||
});
|
||||
am.start(function(err) {
|
||||
err.message.should.equal('destroy');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#stop', function() {
|
||||
it('will close mempool levelup', function(done) {
|
||||
var am = new AddressService({
|
||||
mempoolMemoryIndex: true,
|
||||
node: mocknode
|
||||
});
|
||||
am.mempoolIndex = {};
|
||||
am.mempoolIndex.close = sinon.stub().callsArg(0);
|
||||
am.stop(function() {
|
||||
am.mempoolIndex.close.callCount.should.equal(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#_setMempoolIndexPath', function() {
|
||||
it('should set the database path', function() {
|
||||
var testnode = {
|
||||
network: Networks.livenet,
|
||||
datadir: process.env.HOME + '/.bitcoin',
|
||||
services: {
|
||||
bitcoind: {
|
||||
on: sinon.stub()
|
||||
}
|
||||
}
|
||||
};
|
||||
var am = new AddressService({
|
||||
mempoolMemoryIndex: true,
|
||||
node: testnode
|
||||
});
|
||||
am._setMempoolIndexPath();
|
||||
am.mempoolIndexPath.should.equal(process.env.HOME + '/.bitcoin/bitcore-addressmempool.db');
|
||||
});
|
||||
it('should load the db for testnet', function() {
|
||||
var testnode = {
|
||||
network: Networks.testnet,
|
||||
datadir: process.env.HOME + '/.bitcoin',
|
||||
services: {
|
||||
bitcoind: {
|
||||
on: sinon.stub()
|
||||
}
|
||||
}
|
||||
};
|
||||
var am = new AddressService({
|
||||
mempoolMemoryIndex: true,
|
||||
node: testnode
|
||||
});
|
||||
am._setMempoolIndexPath();
|
||||
am.mempoolIndexPath.should.equal(process.env.HOME + '/.bitcoin/testnet3/bitcore-addressmempool.db');
|
||||
});
|
||||
it('error with unknown network', function() {
|
||||
var testnode = {
|
||||
network: 'unknown',
|
||||
datadir: process.env.HOME + '/.bitcoin',
|
||||
services: {
|
||||
bitcoind: {
|
||||
on: sinon.stub()
|
||||
}
|
||||
}
|
||||
};
|
||||
(function() {
|
||||
var am = new AddressService({
|
||||
mempoolMemoryIndex: true,
|
||||
node: testnode
|
||||
});
|
||||
}).should.throw('Unknown network');
|
||||
});
|
||||
it('should load the db with regtest', function() {
|
||||
// Switch to use regtest
|
||||
// Networks.remove(Networks.testnet);
|
||||
Networks.add({
|
||||
name: 'regtest',
|
||||
alias: 'regtest',
|
||||
pubkeyhash: 0x6f,
|
||||
privatekey: 0xef,
|
||||
scripthash: 0xc4,
|
||||
xpubkey: 0x043587cf,
|
||||
xprivkey: 0x04358394,
|
||||
networkMagic: 0xfabfb5da,
|
||||
port: 18444,
|
||||
dnsSeeds: [ ]
|
||||
});
|
||||
var regtest = Networks.get('regtest');
|
||||
var testnode = {
|
||||
network: regtest,
|
||||
datadir: process.env.HOME + '/.bitcoin',
|
||||
services: {
|
||||
bitcoind: {
|
||||
on: sinon.stub()
|
||||
}
|
||||
}
|
||||
};
|
||||
var am = new AddressService({
|
||||
mempoolMemoryIndex: true,
|
||||
node: testnode
|
||||
});
|
||||
am.mempoolIndexPath.should.equal(process.env.HOME + '/.bitcoin/regtest/bitcore-addressmempool.db');
|
||||
Networks.remove(regtest);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getAPIMethods', function() {
|
||||
it('should return the correct methods', function() {
|
||||
var am = new AddressService({
|
||||
@ -791,6 +1045,50 @@ describe('Address Service', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#_getSpentMempool', function() {
|
||||
it('will decode data from the database', function() {
|
||||
var am = new AddressService({
|
||||
mempoolMemoryIndex: true,
|
||||
node: mocknode
|
||||
});
|
||||
am.mempoolIndex = {};
|
||||
var mempoolValue = Buffer.concat([
|
||||
new Buffer('85630d684f1f414264f88a31bddfc79dd0c00659330dcdc393b321c121f4078b', 'hex'),
|
||||
new Buffer('00000003', 'hex')
|
||||
]);
|
||||
am.mempoolIndex.get = sinon.stub().callsArgWith(1, null, mempoolValue);
|
||||
var prevTxIdBuffer = new Buffer('e7888264d286be2da26b0a4dbd2fc5c9ece82b3e40e6791b137e4155b6da8981', 'hex');
|
||||
var outputIndex = 1;
|
||||
var outputIndexBuffer = new Buffer('00000001', 'hex');
|
||||
var expectedKey = Buffer.concat([
|
||||
new Buffer('03', 'hex'),
|
||||
prevTxIdBuffer,
|
||||
outputIndexBuffer
|
||||
]).toString('hex');
|
||||
am._getSpentMempool(prevTxIdBuffer, outputIndex, function(err, value) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
am.mempoolIndex.get.args[0][0].toString('hex').should.equal(expectedKey);
|
||||
value.inputTxId.should.equal('85630d684f1f414264f88a31bddfc79dd0c00659330dcdc393b321c121f4078b');
|
||||
value.inputIndex.should.equal(3);
|
||||
});
|
||||
});
|
||||
it('handle error from levelup', function() {
|
||||
var am = new AddressService({
|
||||
mempoolMemoryIndex: true,
|
||||
node: mocknode
|
||||
});
|
||||
am.mempoolIndex = {};
|
||||
am.mempoolIndex.get = sinon.stub().callsArgWith(1, new Error('test'));
|
||||
var prevTxIdBuffer = new Buffer('e7888264d286be2da26b0a4dbd2fc5c9ece82b3e40e6791b137e4155b6da8981', 'hex');
|
||||
var outputIndex = 1;
|
||||
am._getSpentMempool(prevTxIdBuffer, outputIndex, function(err) {
|
||||
err.message.should.equal('test');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getOutputs', function() {
|
||||
var am;
|
||||
var address = '1KiW1A4dx1oRgLHtDtBjcunUGkYtFgZ1W';
|
||||
@ -935,6 +1233,93 @@ describe('Address Service', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#_getOutputsMempool', function() {
|
||||
var am;
|
||||
var address = '1KiW1A4dx1oRgLHtDtBjcunUGkYtFgZ1W';
|
||||
var hashBuffer = bitcore.Address(address).hashBuffer;
|
||||
var db = {
|
||||
tip: {
|
||||
__height: 1
|
||||
}
|
||||
};
|
||||
var testnode = {
|
||||
network: Networks.testnet,
|
||||
datadir: 'testdir',
|
||||
services: {
|
||||
db: db,
|
||||
bitcoind: {
|
||||
on: sinon.stub()
|
||||
}
|
||||
}
|
||||
};
|
||||
before(function() {
|
||||
am = new AddressService({
|
||||
mempoolMemoryIndex: true,
|
||||
node: testnode
|
||||
});
|
||||
});
|
||||
it('it will handle error', function(done) {
|
||||
var testStream = new EventEmitter();
|
||||
am.mempoolIndex = {};
|
||||
am.mempoolIndex.createReadStream = sinon.stub().returns(testStream);
|
||||
am._getOutputsMempool(address, hashBuffer, function(err, outputs) {
|
||||
should.exist(err);
|
||||
err.message.should.equal('readstreamerror');
|
||||
done();
|
||||
});
|
||||
testStream.emit('error', new Error('readstreamerror'));
|
||||
setImmediate(function() {
|
||||
testStream.emit('close');
|
||||
});
|
||||
});
|
||||
it('it will parse data', function(done) {
|
||||
var testStream = new EventEmitter();
|
||||
am.mempoolIndex = {};
|
||||
am.mempoolIndex.createReadStream = sinon.stub().returns(testStream);
|
||||
|
||||
am._getOutputsMempool(address, hashBuffer, function(err, outputs) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
outputs.length.should.equal(1);
|
||||
outputs[0].address.should.equal(address);
|
||||
outputs[0].txid.should.equal(txid);
|
||||
outputs[0].outputIndex.should.equal(outputIndex);
|
||||
outputs[0].height.should.equal(-1);
|
||||
outputs[0].satoshis.should.equal(3);
|
||||
outputs[0].script.should.equal('ac');
|
||||
outputs[0].confirmations.should.equal(0);
|
||||
done();
|
||||
});
|
||||
|
||||
var txid = '5d32f0fff6871c377e00c16f48ebb5e89c723d0b9dd25f68fdda70c3392bee61';
|
||||
var txidBuffer = new Buffer(txid, 'hex');
|
||||
var outputIndex = 3;
|
||||
var outputIndexBuffer = new Buffer(4);
|
||||
outputIndexBuffer.writeUInt32BE(outputIndex);
|
||||
var keyData = Buffer.concat([
|
||||
new Buffer('01', 'hex'),
|
||||
hashBuffer,
|
||||
txidBuffer,
|
||||
outputIndexBuffer
|
||||
]);
|
||||
|
||||
var valueData = Buffer.concat([
|
||||
new Buffer('4008000000000000', 'hex'),
|
||||
new Buffer('ac', 'hex')
|
||||
]);
|
||||
|
||||
// Note: key is not used currently
|
||||
testStream.emit('data', {
|
||||
key: keyData,
|
||||
value: valueData
|
||||
});
|
||||
setImmediate(function() {
|
||||
testStream.emit('close');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getUnspentOutputs', function() {
|
||||
it('should concatenate utxos for multiple addresses, even those with none found', function(done) {
|
||||
var addresses = {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user