diff --git a/lib/content/read.js b/lib/content/read.js index 64cb398..a8a0252 100644 --- a/lib/content/read.js +++ b/lib/content/read.js @@ -46,12 +46,10 @@ function hasContent (cache, address, algorithm) { if (!address) { return BB.resolve(false) } return fs.lstatAsync( contentPath(cache, address, algorithm || 'sha512') - ).then(() => true).catch(err => { - if (err && err.code === 'ENOENT') { - return BB.resolve(false) - } else if (err && process.platform === 'win32' && err.code === 'EPERM') { - return BB.resolve(false) - } else { + ).then(() => true) + .catch({code: 'ENOENT'}, () => false) + .catch({code: 'EPERM'}, err => { + if (process.platform !== 'win32') { throw err } }) diff --git a/test/content.read.js b/test/content.read.js index e358b41..34f9160 100644 --- a/test/content.read.js +++ b/test/content.read.js @@ -4,6 +4,7 @@ const Buffer = require('safe-buffer').Buffer const BB = require('bluebird') const crypto = require('crypto') +const finished = BB.promisify(require('mississippi').finished) const path = require('path') const Tacks = require('tacks') const test = require('tap').test @@ -37,15 +38,18 @@ test('read.stream: returns a stream with cache content data', function (t) { stream.on('error', function (e) { throw e }) let buf = '' stream.on('data', function (data) { buf += data }) - stream.on('end', function () { - t.ok(true, 'stream completed successfully') - t.deepEqual(Buffer.from(buf), CONTENT, 'cache contents read correctly') - t.end() - }) + return BB.join( + finished(stream).then(() => Buffer.from(buf)), + read(CACHE, DIGEST), + (fromStream, fromBulk) => { + t.deepEqual(fromStream, CONTENT, 'stream data checks out') + t.deepEqual(fromBulk, CONTENT, 'promise data checks out') + } + ) }) -test('read.stream: allows hashAlgorithm configuration', function (t) { - const CONTENT = 'foobarbaz' +test('read: allows hashAlgorithm configuration', function (t) { + const CONTENT = Buffer.from('foobarbaz') const HASH = 'whirlpool' const DIGEST = crypto.createHash(HASH).update(CONTENT).digest('hex') const fixture = new Tacks(CacheContent({ @@ -56,44 +60,78 @@ test('read.stream: allows hashAlgorithm configuration', function (t) { stream.on('error', function (e) { throw e }) let buf = '' stream.on('data', function (data) { buf += data }) - stream.on('end', function () { - t.ok(true, 'stream completed successfully, off a sha512') - t.deepEqual(buf, CONTENT, 'cache contents read correctly') - t.end() - }) + return BB.join( + finished(stream).then(() => Buffer.from(buf)), + read(CACHE, DIGEST, { + hashAlgorithm: HASH + }), + (fromStream, fromBulk) => { + t.deepEqual(fromStream, CONTENT, 'stream used algorithm') + t.deepEqual(fromBulk, CONTENT, 'promise used algorithm') + } + ) }) -test('read.stream: errors if content missing', function (t) { +test('read: errors if content missing', function (t) { const stream = read.stream(CACHE, 'whatnot') - stream.on('error', function (e) { - t.ok(e, 'got an error!') - t.equal(e.code, 'ENOENT', 'error uses ENOENT error code') - t.end() - }) stream.on('data', function (data) { throw new Error('unexpected data: ' + JSON.stringify(data)) }) stream.on('end', function () { throw new Error('end was called even though stream errored') }) + return BB.join( + finished(stream).catch({code: 'ENOENT'}, err => err), + read(CACHE, 'whatnot').catch({code: 'ENOENT'}, err => err), + (streamErr, bulkErr) => { + t.equal(streamErr.code, 'ENOENT', 'stream got the right error') + t.equal(bulkErr.code, 'ENOENT', 'bulk got the right error') + } + ) }) -test('read.stream: errors if content fails checksum', function (t) { - const CONTENT = 'foobarbaz' +test('read: errors if content fails checksum', function (t) { + const CONTENT = Buffer.from('foobarbaz') const DIGEST = crypto.createHash('sha512').update(CONTENT).digest('hex') const fixture = new Tacks(CacheContent({ [DIGEST]: CONTENT.slice(3) // invalid contents! })) fixture.create(CACHE) const stream = read.readStream(CACHE, DIGEST) - stream.on('error', function (e) { - t.ok(e, 'got an error!') - t.equal(e.code, 'EBADCHECKSUM', 'error uses EBADCHECKSUM error code') - t.end() + stream.on('end', function () { + throw new Error('end was called even though stream errored') }) + return BB.join( + finished(stream).catch({code: 'EBADCHECKSUM'}, err => err), + read(CACHE, DIGEST).catch({code: 'EBADCHECKSUM'}, err => err), + (streamErr, bulkErr) => { + t.equal(streamErr.code, 'EBADCHECKSUM', 'stream got the right error') + t.equal(bulkErr.code, 'EBADCHECKSUM', 'bulk got the right error') + } + ) +}) + +test('read: errors if content size does not match size option', function (t) { + const CONTENT = Buffer.from('foobarbaz') + const DIGEST = crypto.createHash('sha512').update(CONTENT).digest('hex') + const fixture = new Tacks(CacheContent({ + [DIGEST]: CONTENT.slice(3) // bad size! + })) + fixture.create(CACHE) + const stream = read.readStream(CACHE, DIGEST, { size: CONTENT.length }) stream.on('end', function () { throw new Error('end was called even though stream errored') }) + return BB.join( + finished(stream).catch({code: 'EBADSIZE'}, err => err), + read(CACHE, DIGEST, { + size: CONTENT.length + }).catch({code: 'EBADSIZE'}, err => err), + (streamErr, bulkErr) => { + t.equal(streamErr.code, 'EBADSIZE', 'stream got the right error') + t.equal(bulkErr.code, 'EBADSIZE', 'bulk got the right error') + } + ) }) test('hasContent: returns true when a cache file exists', function (t) {