From 5a885f5379be410747429094df86577df8241cfe Mon Sep 17 00:00:00 2001 From: haad Date: Fri, 17 Nov 2017 09:55:31 +0100 Subject: [PATCH 1/2] fix: Add tests for .block promise API Add test for callback-based .rm() Add test for all promise-based functions --- src/block.js | 269 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 196 insertions(+), 73 deletions(-) diff --git a/src/block.js b/src/block.js index d0cf8af6..d26ee4ca 100644 --- a/src/block.js +++ b/src/block.js @@ -7,6 +7,7 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) +const series = require('async/series') const Block = require('ipfs-block') const multihash = require('multihashes') const CID = require('cids') @@ -22,9 +23,10 @@ module.exports = (common) => { let ipfs before(function (done) { - // CI takes longer to instantiate the daemon, so we need to increase the - // timeout for the before step - this.timeout(60 * 1000) + // CI takes longer to instantiate the daemon, + // so we need to increase the timeout for the + // before step + this.timeout(20 * 1000) common.setup((err, factory) => { expect(err).to.not.exist() @@ -38,108 +40,229 @@ module.exports = (common) => { after((done) => common.teardown(done)) - describe('.put', () => { - it('a buffer, using defaults', (done) => { - const expectedHash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' - const blob = new Buffer('blorb') + describe('callback API', () => { + describe('.put', () => { + it('a buffer, using defaults', (done) => { + const expectedHash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' + const blob = new Buffer('blorb') - ipfs.block.put(blob, (err, block) => { - expect(err).to.not.exist() - expect(block.data).to.be.eql(blob) - expectKey(block, multihash.fromB58String(expectedHash), done) + ipfs.block.put(blob, (err, block) => { + expect(err).to.not.exist() + expect(block.data).to.be.eql(blob) + expectKey(block, multihash.fromB58String(expectedHash), done) + }) }) - }) - it('a buffer, using CID', (done) => { - const expectedHash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' - const cid = new CID(expectedHash) - const blob = new Buffer('blorb') + it('a buffer, using CID', (done) => { + const expectedHash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' + const cid = new CID(expectedHash) + const blob = new Buffer('blorb') - ipfs.block.put(blob, { cid: cid }, (err, block) => { - expect(err).to.not.exist() - expect(block.data).to.be.eql(blob) - expectKey(block, multihash.fromB58String(expectedHash), done) + ipfs.block.put(blob, { cid: cid }, (err, block) => { + expect(err).to.not.exist() + expect(block.data).to.be.eql(blob) + expectKey(block, multihash.fromB58String(expectedHash), done) + }) }) - }) - it('a buffer, using options', (done) => { - const expectedHash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' - const blob = new Buffer('blorb') + it('a buffer, using options', (done) => { + const expectedHash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' + const blob = new Buffer('blorb') - ipfs.block.put(blob, { - format: 'dag-pb', - mhtype: 'sha2-256', - version: 0 - }, (err, block) => { - expect(err).to.not.exist() - expect(block.data).to.be.eql(blob) - expectKey(block, multihash.fromB58String(expectedHash), done) + ipfs.block.put(blob, { + format: 'dag-pb', + mhtype: 'sha2-256', + version: 0 + }, (err, block) => { + expect(err).to.not.exist() + expect(block.data).to.be.eql(blob) + expectKey(block, multihash.fromB58String(expectedHash), done) + }) + }) + + it('a Block instance', (done) => { + const expectedHash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' + const cid = new CID(expectedHash) + const b = new Block(new Buffer('blorb'), cid) + + ipfs.block.put(b, (err, block) => { + expect(err).to.not.exist() + expect(block.data).to.eql(new Buffer('blorb')) + expectKey(block, multihash.fromB58String(expectedHash), done) + }) + }) + + it('error with array of blocks', (done) => { + const blob = Buffer('blorb') + + ipfs.block.put([blob, blob], (err) => { + expect(err).to.be.an.instanceof(Error) + done() + }) }) }) - it('a Block instance', (done) => { - const expectedHash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' - const cid = new CID(expectedHash) - const b = new Block(new Buffer('blorb'), cid) + describe('.get', () => { + it('by CID object', (done) => { + const hash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' + const cid = new CID(hash) - ipfs.block.put(b, (err, block) => { - expect(err).to.not.exist() - expect(block.data).to.eql(new Buffer('blorb')) - expectKey(block, multihash.fromB58String(expectedHash), done) + ipfs.block.get(cid, (err, block) => { + expect(err).to.not.exist() + expect(block.data).to.eql(new Buffer('blorb')) + expectKey(block, cid.multihash, done) + }) + }) + + it('by CID in Str', (done) => { + const hash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' + + ipfs.block.get(hash, (err, block) => { + expect(err).to.not.exist() + expect(block.data).to.eql(new Buffer('blorb')) + expectKey(block, multihash.fromB58String(hash), done) + }) }) }) - it('error with array of blocks', (done) => { - const blob = Buffer('blorb') + describe('.stat', () => { + it('by CID', (done) => { + const hash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' + const cid = new CID(hash) - ipfs.block.put([blob, blob], (err) => { - expect(err).to.be.an.instanceof(Error) - done() + ipfs.block.stat(cid, (err, stats) => { + expect(err).to.not.exist() + expect(stats).to.have.property('key') + expect(stats).to.have.property('size') + done() + }) }) }) - // TODO it.skip('Promises support', (done) => {}) + describe('.rm', function () { + it('by CID', (done) => { + const expectedHash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' + const cid = new CID(expectedHash) + const b = new Block(new Buffer('blorb'), cid) + + series([ + (cb) => { + // Add a block + ipfs.block.put(b, (err, block) => { + expect(err).to.not.exist() + expect(block.data).to.be.eql(b.data) + expectKey(block, multihash.fromB58String(expectedHash), cb) + }) + }, + (cb) => { + // Remove the block + ipfs.block.rm(cid, (err) => { + expect(err).to.not.exist() + cb() + }) + }, + (cb) => { + // Remove bitswap from IPFS so that block.get tries to fetch the block + // from the local repo (not from the network). This is to make sure we + // get the error (as expected) instead of waiting for a timeout. + ipfs._blockService._bitswap = null + // Verify that the block was removed + ipfs.block.get(cid, (err, block) => { + expect(err).to.exist() + expect(block).to.not.exist() + // Verifying the error message with a function due to chai + // NOT supporting .to.include.any([str1, str2]) + expect(err.toString()).to.satisfy((str) => { + return str.indexOf('Error: ENOENT: no such file or directory') > -1 || + str.indexOf('NotFoundError: Key not found in database') > -1 + }) + cb() + }) + } + ], done) + }) + }) }) - describe('.get', () => { - it('by CID object', (done) => { - const hash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' - const cid = new CID(hash) + describe('promise API', () => { + describe('.put', () => { + it('a buffer, using defaults', (done) => { + const expectedHash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' + const blob = new Buffer('blorb') - ipfs.block.get(cid, (err, block) => { - expect(err).to.not.exist() - expect(block.data).to.eql(new Buffer('blorb')) - expectKey(block, cid.multihash, done) + ipfs.block.put(blob) + .then((block) => { + expect(block.data).to.be.eql(blob) + expectKey(block, multihash.fromB58String(expectedHash), done) + }) + .catch(done) }) }) - it('by CID in Str', (done) => { - const hash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' + describe('.get', () => { + it('by CID object', (done) => { + const hash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' + const cid = new CID(hash) - ipfs.block.get(hash, (err, block) => { - expect(err).to.not.exist() - expect(block.data).to.eql(new Buffer('blorb')) - expectKey(block, multihash.fromB58String(hash), done) + ipfs.block.get(cid) + .then((block) => { + expect(block.data).to.eql(new Buffer('blorb')) + expectKey(block, cid.multihash, done) + }) + .catch(done) }) }) - // TODO it.skip('Promises support', (done) => {}) - }) - - describe('.stat', () => { - it('by CID', (done) => { - const hash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' - const cid = new CID(hash) + describe('.stat', () => { + it('by CID', (done) => { + const hash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' + const cid = new CID(hash) - ipfs.block.stat(cid, (err, stats) => { - expect(err).to.not.exist() - expect(stats).to.have.property('key') - expect(stats).to.have.property('size') - done() + ipfs.block.stat(cid) + .then((stats) => { + expect(stats).to.have.property('key') + expect(stats).to.have.property('size') + done() + }) + .catch(done) }) }) - // TODO it.skip('Promises support', (done) => {}) + describe('.rm', function () { + it('by CID', (done) => { + const expectedHash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' + const cid = new CID(expectedHash) + const b = new Block(new Buffer('blorb'), cid) + + ipfs.block.put(b) + .then((block) => { + expect(block.data).to.be.eql(b.data) + }) + .then(() => ipfs.block.rm(cid)) // Remove the block + .then(() => { + // Remove bitswap from IPFS so that block.get tries to fetch the block + // from the local repo (not from the network). This is to make sure we + // get the error (as expected) instead of waiting for a timeout. + ipfs._blockService._bitswap = null + // Verify that the block was removed + return ipfs.block.get(cid) + }) + .then((block) => { + // We should never end here + expect(block).to.not.exist() + done(new Error('Block was not removed!')) + }) + .catch((err) => { + // Verifying the error message with a function due to chai + // NOT supporting .to.include.any([str1, str2]) + expect(err.toString()).to.satisfy((str) => { + return str.indexOf('Error: ENOENT: no such file or directory') > -1 || + str.indexOf('NotFoundError: Key not found in database') > -1 + }) + done() + }) + }) + }) }) }) } From 2da5ef0d340b9367ffae533c058d19da6a796692 Mon Sep 17 00:00:00 2001 From: haad Date: Fri, 17 Nov 2017 10:25:42 +0100 Subject: [PATCH 2/2] Skip .rm() tests for now (see code for details) --- src/block.js | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/block.js b/src/block.js index d26ee4ca..b7ed9a0a 100644 --- a/src/block.js +++ b/src/block.js @@ -26,7 +26,7 @@ module.exports = (common) => { // CI takes longer to instantiate the daemon, // so we need to increase the timeout for the // before step - this.timeout(20 * 1000) + this.timeout(60 * 1000) common.setup((err, factory) => { expect(err).to.not.exist() @@ -140,7 +140,13 @@ module.exports = (common) => { }) describe('.rm', function () { - it('by CID', (done) => { + // We need to skip this part of the test for now: + // By default, block.get() will try to get the block from + // bitswap thus causing a long timeout. What we want here is + // to get the block.get() to return an error as fast as possible, + // indicating that we don't have the block anymore. + // See: https://github.com/ipfs/interface-ipfs-core/pull/170#discussion_r151633508 + it.skip('by CID', (done) => { const expectedHash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' const cid = new CID(expectedHash) const b = new Block(new Buffer('blorb'), cid) @@ -162,10 +168,6 @@ module.exports = (common) => { }) }, (cb) => { - // Remove bitswap from IPFS so that block.get tries to fetch the block - // from the local repo (not from the network). This is to make sure we - // get the error (as expected) instead of waiting for a timeout. - ipfs._blockService._bitswap = null // Verify that the block was removed ipfs.block.get(cid, (err, block) => { expect(err).to.exist() @@ -229,7 +231,13 @@ module.exports = (common) => { }) describe('.rm', function () { - it('by CID', (done) => { + // We need to skip this part of the test for now: + // By default, block.get() will try to get the block from + // bitswap thus causing a long timeout. What we want here is + // to get the block.get() to return an error as fast as possible, + // indicating that we don't have the block anymore. + // See: https://github.com/ipfs/interface-ipfs-core/pull/170#discussion_r151633508 + it.skip('by CID', (done) => { const expectedHash = 'QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ' const cid = new CID(expectedHash) const b = new Block(new Buffer('blorb'), cid) @@ -240,10 +248,6 @@ module.exports = (common) => { }) .then(() => ipfs.block.rm(cid)) // Remove the block .then(() => { - // Remove bitswap from IPFS so that block.get tries to fetch the block - // from the local repo (not from the network). This is to make sure we - // get the error (as expected) instead of waiting for a timeout. - ipfs._blockService._bitswap = null // Verify that the block was removed return ipfs.block.get(cid) })