bitcore-node-zcash/test/db.unit.js

377 lines
12 KiB
JavaScript
Raw Normal View History

2015-07-16 12:53:44 -07:00
'use strict';
var should = require('chai').should();
var sinon = require('sinon');
2015-08-27 07:10:07 -07:00
var index = require('../');
var DB = index.DB;
2015-07-16 12:53:44 -07:00
var blockData = require('./data/livenet-345003.json');
2015-08-27 07:10:07 -07:00
var bitcore = require('bitcore');
var Block = bitcore.Block;
var transactionData = require('./data/bitcoin-transactions.json');
2015-08-27 07:10:07 -07:00
var errors = index.errors;
2015-07-16 12:53:44 -07:00
var memdown = require('memdown');
2015-07-23 08:33:42 -07:00
var inherits = require('util').inherits;
var BaseModule = require('../lib/module');
2015-08-14 13:44:40 -07:00
var bitcore = require('bitcore');
var Transaction = bitcore.Transaction;
2015-07-16 12:53:44 -07:00
describe('Bitcoin DB', function() {
2015-08-21 13:13:11 -07:00
describe('#start', function() {
2015-08-14 13:44:40 -07:00
it('should emit ready', function(done) {
var db = new DB({store: memdown});
db.node = {};
db.node.bitcoind = {
2015-08-14 13:44:40 -07:00
on: sinon.spy()
};
db.addModule = sinon.spy();
2015-08-21 13:13:11 -07:00
var readyFired = false;
db.on('ready', function() {
readyFired = true;
});
db.start(function() {
readyFired.should.equal(true);
done();
});
});
});
describe('#stop', function() {
2015-08-24 10:32:13 -07:00
it('should immediately call the callback', function(done) {
2015-08-21 13:13:11 -07:00
var db = new DB({store: memdown});
db.stop(function(err) {
should.not.exist(err);
done();
});
2015-08-14 13:44:40 -07:00
});
});
describe('#getTransaction', function() {
it('will return a NotFound error', function(done) {
var db = new DB({store: memdown});
db.node = {};
db.node.bitcoind = {
getTransaction: sinon.stub().callsArgWith(2, null, null)
};
var txid = '7426c707d0e9705bdd8158e60983e37d0f5d63529086d6672b07d9238d5aa623';
db.getTransaction(txid, true, function(err) {
err.should.be.instanceof(errors.Transaction.NotFound);
done();
});
});
it('will return an error from bitcoind', function(done) {
var db = new DB({store: memdown});
db.node = {};
db.node.bitcoind = {
getTransaction: sinon.stub().callsArgWith(2, new Error('test error'))
};
var txid = '7426c707d0e9705bdd8158e60983e37d0f5d63529086d6672b07d9238d5aa623';
db.getTransaction(txid, true, function(err) {
err.message.should.equal('test error');
done();
});
});
it('will return an error from bitcoind', function(done) {
var db = new DB({store: memdown});
db.node = {};
db.node.bitcoind = {
getTransaction: sinon.stub().callsArgWith(2, null, new Buffer(transactionData[0].hex, 'hex'))
};
var txid = '7426c707d0e9705bdd8158e60983e37d0f5d63529086d6672b07d9238d5aa623';
db.getTransaction(txid, true, function(err, tx) {
if (err) {
throw err;
}
should.exist(tx);
done();
});
});
});
2015-07-16 12:53:44 -07:00
describe('#getBlock', function() {
var db = new DB({store: memdown});
2015-08-27 07:10:07 -07:00
var blockBuffer = new Buffer(blockData, 'hex');
var expectedBlock = Block.fromBuffer(blockBuffer);
db.node = {};
db.node.bitcoind = {
2015-08-27 07:10:07 -07:00
getBlock: sinon.stub().callsArgWith(1, null, blockBuffer)
2015-07-16 12:53:44 -07:00
};
2015-08-27 07:10:07 -07:00
it('should get the block from bitcoin daemon', function(done) {
2015-07-16 12:53:44 -07:00
db.getBlock('00000000000000000593b60d8b4f40fd1ec080bdb0817d475dae47b5f5b1f735', function(err, block) {
should.not.exist(err);
2015-08-27 07:10:07 -07:00
block.hash.should.equal(expectedBlock.hash);
2015-07-16 12:53:44 -07:00
done();
});
});
it('should give an error when bitcoind.js gives an error', function(done) {
db.node = {};
db.node.bitcoind = {};
db.node.bitcoind.getBlock = sinon.stub().callsArgWith(1, new Error('error'));
2015-07-16 12:53:44 -07:00
db.getBlock('00000000000000000593b60d8b4f40fd1ec080bdb0817d475dae47b5f5b1f735', function(err, block) {
should.exist(err);
err.message.should.equal('error');
done();
});
});
});
describe('#putBlock', function() {
it('should call callback', function(done) {
2015-07-16 12:53:44 -07:00
var db = new DB({store: memdown});
db.putBlock('block', function(err) {
should.not.exist(err);
done();
});
});
});
2015-08-14 13:44:40 -07:00
describe('#getPrevHash', function() {
it('should return prevHash from bitcoind', function(done) {
var db = new DB({store: memdown});
db.node = {};
db.node.bitcoind = {
2015-08-14 13:44:40 -07:00
getBlockIndex: sinon.stub().returns({
prevHash: 'prevhash'
})
};
db.getPrevHash('hash', function(err, prevHash) {
should.not.exist(err);
prevHash.should.equal('prevhash');
done();
});
});
it('should give an error if bitcoind could not find it', function(done) {
var db = new DB({store: memdown});
db.node = {};
db.node.bitcoind = {
2015-08-14 13:44:40 -07:00
getBlockIndex: sinon.stub().returns(null)
};
db.getPrevHash('hash', function(err, prevHash) {
should.exist(err);
done();
});
});
});
describe('#getTransactionWithBlockInfo', function() {
it('should give a transaction with height and timestamp', function(done) {
var txBuffer = new Buffer('01000000016f95980911e01c2c664b3e78299527a47933aac61a515930a8fe0213d1ac9abe01000000da0047304402200e71cda1f71e087c018759ba3427eb968a9ea0b1decd24147f91544629b17b4f0220555ee111ed0fc0f751ffebf097bdf40da0154466eb044e72b6b3dcd5f06807fa01483045022100c86d6c8b417bff6cc3bbf4854c16bba0aaca957e8f73e19f37216e2b06bb7bf802205a37be2f57a83a1b5a8cc511dc61466c11e9ba053c363302e7b99674be6a49fc0147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a9148a31d53a448c18996e81ce67811e5fb7da21e4468738c9d6f90000000017a9148ce5408cfeaddb7ccb2545ded41ef478109454848700000000', 'hex');
var info = {
height: 530482,
timestamp: 1439559434000,
buffer: txBuffer
};
var db = new DB({store: memdown});
db.node = {};
db.node.bitcoind = {
2015-08-14 13:44:40 -07:00
getTransactionWithBlockInfo: sinon.stub().callsArgWith(2, null, info)
};
db.getTransactionWithBlockInfo('2d950d00494caf6bfc5fff2a3f839f0eb50f663ae85ce092bc5f9d45296ae91f', true, function(err, tx) {
should.not.exist(err);
tx.__height.should.equal(info.height);
tx.__timestamp.should.equal(info.timestamp);
done();
});
});
it('should give an error if one occurred', function(done) {
var db = new DB({store: memdown});
db.node = {};
db.node.bitcoind = {
2015-08-14 13:44:40 -07:00
getTransactionWithBlockInfo: sinon.stub().callsArgWith(2, new Error('error'))
};
db.getTransactionWithBlockInfo('tx', true, function(err, tx) {
should.exist(err);
done();
});
});
});
describe('#sendTransaction', function() {
it('should give the txid on success', function(done) {
var db = new DB({store: memdown});
db.node = {};
db.node.bitcoind = {
2015-08-14 13:44:40 -07:00
sendTransaction: sinon.stub().returns('txid')
};
var tx = new Transaction();
db.sendTransaction(tx, function(err, txid) {
should.not.exist(err);
txid.should.equal('txid');
done();
});
});
it('should give an error if bitcoind threw an error', function(done) {
var db = new DB({store: memdown});
db.node = {};
db.node.bitcoind = {
2015-08-14 13:44:40 -07:00
sendTransaction: sinon.stub().throws(new Error('error'))
};
var tx = new Transaction();
db.sendTransaction(tx, function(err, txid) {
should.exist(err);
done();
});
});
});
describe("#estimateFee", function() {
it('should pass along the fee from bitcoind', function(done) {
var db = new DB({store: memdown});
db.node = {};
db.node.bitcoind = {
2015-08-14 13:44:40 -07:00
estimateFee: sinon.stub().returns(1000)
};
db.estimateFee(5, function(err, fee) {
should.not.exist(err);
fee.should.equal(1000);
db.node.bitcoind.estimateFee.args[0][0].should.equal(5);
2015-08-14 13:44:40 -07:00
done();
});
});
});
2015-07-16 12:53:44 -07:00
describe('#getOutputTotal', function() {
it('should return the correct value including the coinbase', function() {
var totals = [10, 20, 30];
var db = new DB({path: 'path', store: memdown});
var transactions = totals.map(function(total) {
return {
_getOutputAmount: function() {
return total;
},
isCoinbase: function() {
return total === 10 ? true : false;
}
};
});
var grandTotal = db.getOutputTotal(transactions);
grandTotal.should.equal(60);
});
it('should return the correct value excluding the coinbase', function() {
var totals = [10, 20, 30];
var db = new DB({path: 'path', store: memdown});
var transactions = totals.map(function(total) {
return {
_getOutputAmount: function() {
return total;
},
isCoinbase: function() {
return total === 10 ? true : false;
}
};
});
var grandTotal = db.getOutputTotal(transactions, true);
grandTotal.should.equal(50);
2015-07-16 12:53:44 -07:00
});
});
describe('#getInputTotal', function() {
it('should return the correct value', function() {
var totals = [10, 20, 30];
var db = new DB({path: 'path', store: memdown});
var transactions = totals.map(function(total) {
return {
_getInputAmount: function() {
return total;
},
isCoinbase: sinon.stub().returns(false)
};
});
var grandTotal = db.getInputTotal(transactions);
grandTotal.should.equal(60);
});
it('should return 0 if the tx is a coinbase', function() {
var db = new DB({store: memdown});
var tx = {
isCoinbase: sinon.stub().returns(true)
};
var total = db.getInputTotal([tx]);
total.should.equal(0);
});
});
2015-07-23 08:33:42 -07:00
describe('#_onChainAddBlock', function() {
it('should remove block from mempool and call blockHandler with true', function(done) {
var db = new DB({store: memdown});
db.mempool = {
removeBlock: sinon.stub()
2015-07-16 12:53:44 -07:00
};
2015-07-23 08:33:42 -07:00
db.blockHandler = sinon.stub().callsArg(2);
db._onChainAddBlock({hash: 'hash'}, function(err) {
2015-07-16 12:53:44 -07:00
should.not.exist(err);
2015-07-23 08:33:42 -07:00
db.blockHandler.args[0][1].should.equal(true);
2015-07-16 12:53:44 -07:00
done();
});
});
});
2015-07-23 08:33:42 -07:00
describe('#_onChainRemoveBlock', function() {
it('should call blockHandler with false', function(done) {
var db = new DB({store: memdown});
db.blockHandler = sinon.stub().callsArg(2);
db._onChainRemoveBlock({hash: 'hash'}, function(err) {
2015-07-16 12:53:44 -07:00
should.not.exist(err);
2015-07-23 08:33:42 -07:00
db.blockHandler.args[0][1].should.equal(false);
2015-07-16 12:53:44 -07:00
done();
});
});
});
2015-07-23 08:33:42 -07:00
describe('#blockHandler', function() {
var db = new DB({store: memdown});
var Module1 = function() {};
Module1.prototype.blockHandler = sinon.stub().callsArgWith(2, null, ['op1', 'op2', 'op3']);
var Module2 = function() {};
Module2.prototype.blockHandler = sinon.stub().callsArgWith(2, null, ['op4', 'op5']);
2015-08-27 13:09:27 -07:00
db.node = {};
db.node.modules = {
module1: new Module1(),
module2: new Module2()
};
2015-07-16 12:53:44 -07:00
db.store = {
batch: sinon.stub().callsArg(1)
};
2015-07-23 08:33:42 -07:00
it('should call blockHandler in all modules and perform operations', function(done) {
db.blockHandler('block', true, function(err) {
2015-07-16 12:53:44 -07:00
should.not.exist(err);
2015-07-23 08:33:42 -07:00
db.store.batch.args[0][0].should.deep.equal(['op1', 'op2', 'op3', 'op4', 'op5']);
2015-07-16 12:53:44 -07:00
done();
});
});
2015-07-23 08:33:42 -07:00
it('should give an error if one of the modules gives an error', function(done) {
var Module3 = function() {};
Module3.prototype.blockHandler = sinon.stub().callsArgWith(2, new Error('error'));
db.node.modules.module3 = new Module3();
2015-07-23 08:33:42 -07:00
db.blockHandler('block', true, function(err) {
2015-07-16 12:53:44 -07:00
should.exist(err);
done();
});
});
});
describe('#getAPIMethods', function() {
2015-07-23 08:33:42 -07:00
it('should return the correct db methods', function() {
var db = new DB({store: memdown});
2015-08-27 13:09:27 -07:00
db.node = {};
db.node.modules = {};
2015-07-16 12:53:44 -07:00
var methods = db.getAPIMethods();
2015-08-28 13:06:26 -07:00
methods.length.should.equal(5);
2015-07-16 12:53:44 -07:00
});
});
});