Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests for cache command #2122

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions lib/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ const usage = usageUtil('cache',
const completion = (opts, cb) => {
const argv = opts.conf.argv.remain
if (argv.length === 2)
return cb(null, ['add', 'clean'])
return cb(null, ['add', 'clean', 'verify'])

// TODO - eventually...
switch (argv[2]) {
case 'verify':
case 'clean':
case 'add':
return cb(null, [])
Expand All @@ -40,11 +41,11 @@ const cache = async (args) => {
case 'rm': case 'clear': case 'clean':
return await clean(args)
case 'add':
return await add(args, npm.prefix)
return await add(args)
case 'verify': case 'check':
return await verify()
default:
throw usage
throw Object.assign(new Error(usage), { code: 'EUSAGE' })
}
}

Expand Down Expand Up @@ -77,22 +78,21 @@ with --force.`)
// npm cache add <pkg> <ver>
// npm cache add <tarball>
// npm cache add <folder>
const add = async (args, where) => {
const add = async (args) => {
const usage = 'Usage:\n' +
' npm cache add <tarball-url>\n' +
' npm cache add <pkg>@<ver>\n' +
' npm cache add <tarball>\n' +
' npm cache add <folder>\n'
log.silly('cache add', 'args', args)
const spec = args[0] +
const spec = args[0] && args[0] +
(args[1] === undefined || args[1] === null ? '' : `@${args[1]}`)

log.verbose('cache add', 'spec', spec)
if (!spec)
throw new Error(usage)
throw Object.assign(new Error(usage), { code: 'EUSAGE' })

log.silly('cache add', 'parsed spec', spec)
const opts = { ...npm.flatOptions, where }
log.silly('cache add', 'spec', spec)
const opts = { ...npm.flatOptions }

// we ask pacote for the thing, and then just throw the data
// away so that it tee-pipes it into the cache like it does
Expand All @@ -109,7 +109,7 @@ const verify = async () => {
? `~${cache.substr(process.env.HOME.length)}`
: cache
const stats = await cacache.verify(cache)
output(`Cache verified and compressed (${prefix}):`)
output(`Cache verified and compressed (${prefix})`)
output(`Content verified: ${stats.verifiedContent} (${stats.keptSize} bytes)`)
stats.badContentCount && output(`Corrupted content removed: ${stats.badContentCount}`)
stats.reclaimedCount && output(`Content garbage-collected: ${stats.reclaimedCount} (${stats.reclaimedSize} bytes)`)
Expand Down
232 changes: 232 additions & 0 deletions test/lib/cache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
const t = require('tap')
const requireInject = require('require-inject')
const path = require('path')

const usageUtil = () => 'usage instructions'

const flatOptions = {
force: false
}

const npm = {
flatOptions,
cache: '/fake/path'
}

let rimrafPath = ''
const rimraf = (path, cb) => {
rimrafPath = path
return cb()
}

let logOutput = []
const npmlog = {
silly: (...args) => {
logOutput.push(['silly', ...args])
}
}

let tarballStreamSpec = ''
let tarballStreamOpts = {}
const pacote = {
tarball: {
stream: (spec, cb, opts) => {
tarballStreamSpec = spec
tarballStreamOpts = opts
return cb({
resume: () => {},
promise: () => Promise.resolve()
})
}
}
}

let outputOutput = []
const output = (msg) => {
outputOutput.push(msg)
}

let cacacheVerifyPath = ''
const cacacheVerifyStats = {
keptSize: 100,
verifiedContent: 1,
totalEntries: 1,
runTime: { total: 2000 }
}
const cacache = {
verify: (path) => {
cacacheVerifyPath = path
return cacacheVerifyStats
}
}

const mocks = {
cacache,
npmlog,
pacote,
rimraf,
'../../lib/npm.js': npm,
'../../lib/utils/output.js': output,
'../../lib/utils/usage.js': usageUtil
}

const cache = requireInject('../../lib/cache.js', mocks)

t.test('cache no args', t => {
cache([], err => {
t.equal(err.message, 'usage instructions', 'should throw usage instructions')
t.end()
})
})

t.test('cache clean', t => {
cache(['clean'], err => {
t.match(err.message, 'the npm cache self-heals', 'should throw warning')
t.end()
})
})

t.test('cache clean (force)', t => {
flatOptions.force = true
t.teardown(() => {
rimrafPath = ''
flatOptions.force = false
})

cache(['clear'], err => {
t.ifError(err)
t.equal(rimrafPath, path.join(npm.cache, '_cacache'))
t.end()
})
})

t.test('cache clean with arg', t => {
cache(['rm', 'pkg'], err => {
t.match(err.message, 'does not accept arguments', 'should throw error')
t.end()
})
})

t.test('cache add no arg', t => {
t.teardown(() => {
logOutput = []
})

cache(['add'], err => {
t.strictSame(logOutput, [
['silly', 'cache add', 'args', []],
], 'logs correctly')
t.equal(err.code, 'EUSAGE', 'throws usage error')
t.end()
})
})

t.test('cache add pkg only', t => {
t.teardown(() => {
logOutput = []
tarballStreamSpec = ''
tarballStreamOpts = {}
})

cache(['add', 'mypkg'], err => {
t.ifError(err)
t.strictSame(logOutput, [
['silly', 'cache add', 'args', ['mypkg']],
['silly', 'cache add', 'spec', 'mypkg']
], 'logs correctly')
t.equal(tarballStreamSpec, 'mypkg', 'passes the correct spec to pacote')
t.same(tarballStreamOpts, flatOptions, 'passes the correct options to pacote')
t.end()
})
})

t.test('cache add pkg w/ spec modifier', t => {
t.teardown(() => {
logOutput = []
tarballStreamSpec = ''
tarballStreamOpts = {}
})

cache(['add', 'mypkg', 'latest'], err => {
t.ifError(err)
t.strictSame(logOutput, [
['silly', 'cache add', 'args', ['mypkg', 'latest']],
['silly', 'cache add', 'spec', 'mypkg@latest']
], 'logs correctly')
t.equal(tarballStreamSpec, 'mypkg@latest', 'passes the correct spec to pacote')
t.same(tarballStreamOpts, flatOptions, 'passes the correct options to pacote')
t.end()
})
})

t.test('cache verify', t => {
t.teardown(() => {
outputOutput = []
cacacheVerifyPath = ''
})

cache(['verify'], err => {
t.ifError(err)
t.match(outputOutput, [
`Cache verified and compressed (${path.join(npm.cache, '_cacache')})`,
'Content verified: 1 (100 bytes)',
'Index entries: 1',
'Finished in 2s'
], 'prints correct output')
t.end()
})
})

t.test('cache verify w/ extra output', t => {
npm.cache = `${process.env.HOME}/fake/path`
cacacheVerifyStats.badContentCount = 1
cacacheVerifyStats.reclaimedCount = 2
cacacheVerifyStats.reclaimedSize = 200
cacacheVerifyStats.missingContent = 3
t.teardown(() => {
npm.cache = '/fake/path'
outputOutput = []
cacacheVerifyPath = ''
delete cacacheVerifyStats.badContentCount
delete cacacheVerifyStats.reclaimedCount
delete cacacheVerifyStats.reclaimedSize
delete cacacheVerifyStats.missingContent
})

cache(['check'], err => {
t.ifError(err)
t.match(outputOutput, [
`Cache verified and compressed (~${path.join('/fake/path', '_cacache')})`,
'Content verified: 1 (100 bytes)',
'Corrupted content removed: 1',
'Content garbage-collected: 2 (200 bytes)',
'Missing content: 3',
'Index entries: 1',
'Finished in 2s'
], 'prints correct output')
t.end()
})
})

t.test('cache completion', t => {
const { completion } = cache

const testComp = (argv, expect) => {
completion({ conf: { argv: { remain: argv } } }, (err, res) => {
t.ifError(err)
t.strictSame(res, expect, argv.join(' '))
})
}

testComp(['npm', 'cache'], [
'add',
'clean',
'verify'
])

testComp(['npm', 'cache', 'add'], [])
testComp(['npm', 'cache', 'clean'], [])
testComp(['npm', 'cache', 'verify'], [])

t.end()
})