You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

309 lines
9.1 KiB

var test = require('tape')
var fs = require('fs')
var rm = require('rimraf')
var path = require('path')
var http = require('http')
var https = require('https')
var download = require('../download')
var rc = require('../rc')
var util = require('../util')
var error = require('../error')
var build = path.join(__dirname, 'build')
var unpacked = path.join(build, 'Release/leveldown.node')
test('downloading from GitHub, not cached', function (t) {
t.plan(14)
rm.sync(build)
rm.sync(util.prebuildCache())
var opts = getOpts()
var downloadUrl = util.getDownloadUrl(opts)
var cachedPrebuild = util.cachedPrebuild(downloadUrl)
var npmCache = util.npmCache()
var tempFile
var existsCallNum = 0
var _access = fs.access ? fs.access.bind(fs) : fs.access
var _exists = fs.exists.bind(fs)
if (_access) {
fs.access = function (path, a, cb) {
if (existsCallNum++ === 0) {
t.equal(path, npmCache, 'fs.exists called for npm cache')
_access(path, cb)
}
}
}
fs.exists = function (path, cb) {
if (existsCallNum++ === 0) {
t.equal(path, npmCache, 'fs.exists called for npm cache')
_exists(path, cb)
} else {
t.equal(path, cachedPrebuild, 'fs.exists called for prebuild')
_exists(path, function (exists) {
t.equal(exists, false, 'prebuild should be cached')
cb(exists)
})
}
}
var mkdirCount = 0
var _mkdir = fs.mkdir.bind(fs)
fs.mkdir = function () {
var args = [].slice.call(arguments)
if (mkdirCount++ === 0) {
t.equal(args[0], util.prebuildCache(), 'fs.mkdir called for prebuildCache')
}
_mkdir.apply(fs, arguments)
}
var writeStreamCount = 0
var _createWriteStream = fs.createWriteStream.bind(fs)
fs.createWriteStream = function (path) {
if (writeStreamCount++ === 0) {
tempFile = path
t.ok(/\.tmp$/i.test(path), 'this is the temporary file')
} else {
t.ok(/\.node$/i.test(path), 'this is the unpacked file')
}
return _createWriteStream(path)
}
var _createReadStream = fs.createReadStream.bind(fs)
fs.createReadStream = function (path) {
t.equal(path, cachedPrebuild, 'createReadStream called for cachedPrebuild')
return _createReadStream(path)
}
var _request = https.request
https.request = function (opts) {
https.request = _request
t.equal('https://' + opts.hostname + opts.path, downloadUrl, 'correct url')
return _request.apply(https, arguments)
}
t.equal(fs.existsSync(build), false, 'no build folder')
download(opts, function (err) {
t.error(err, 'no error')
t.equal(fs.existsSync(util.prebuildCache()), true, 'prebuildCache created')
t.equal(fs.existsSync(cachedPrebuild), true, 'prebuild was cached')
t.equal(fs.existsSync(unpacked), true, unpacked + ' should exist')
t.equal(fs.existsSync(tempFile), false, 'temp file should be gone')
fs.exists = _exists
fs.access = _access
fs.mkdir = _mkdir
fs.createWriteStream = _createWriteStream
fs.createReadStream = _createReadStream
})
})
test('cached prebuild', function (t) {
t.plan(8)
rm.sync(build)
var opts = getOpts()
var downloadUrl = util.getDownloadUrl(opts)
var cachedPrebuild = util.cachedPrebuild(downloadUrl)
var npmCache = util.npmCache()
var existsCallNum = 0
var _access = fs.access ? fs.access.bind(fs) : fs.access
var _exists = fs.exists.bind(fs)
if (_access) {
fs.access = function (path, a, cb) {
if (existsCallNum++ === 0) {
t.equal(path, npmCache, 'fs.exists called for npm cache')
_access(path, cb)
}
}
}
fs.exists = function (path, cb) {
if (existsCallNum++ === 0) {
t.equal(path, npmCache, 'fs.exists called for npm cache')
_exists(path, cb)
} else {
t.equal(path, cachedPrebuild, 'fs.exists called for prebuild')
_exists(path, function (exists) {
t.equal(exists, true, 'prebuild should be cached')
cb(exists)
})
}
}
var _createWriteStream = fs.createWriteStream.bind(fs)
fs.createWriteStream = function (path) {
t.ok(/\.node$/i.test(path), 'this is the unpacked file')
return _createWriteStream(path)
}
var _createReadStream = fs.createReadStream.bind(fs)
fs.createReadStream = function (path) {
t.equal(path, cachedPrebuild, 'createReadStream called for cachedPrebuild')
return _createReadStream(path)
}
t.equal(fs.existsSync(build), false, 'no build folder')
download(opts, function (err) {
t.error(err, 'no error')
t.equal(fs.existsSync(unpacked), true, unpacked + ' should exist')
fs.createReadStream = _createReadStream
fs.createWriteStream = _createWriteStream
fs.exists = _exists
fs.access = _access
})
})
test('missing .node file in .tar.gz should fail', function (t) {
t.plan(2)
var opts = getOpts()
opts.updateName = function (entry) {
t.ok(/\.node$/i.test(entry.name), 'should match but we pretend it does not')
}
download(opts, function (err) {
t.equal(err.message, 'Missing .node file in archive', 'correct error message')
t.end()
})
})
test('non existing host should fail with no dangling temp file', function (t) {
t.plan(3)
var opts = getOpts()
opts.pkg.binary = {
host: 'https://foo.bar.baz'
}
var downloadUrl = util.getDownloadUrl(opts)
var cachedPrebuild = util.cachedPrebuild(downloadUrl)
var _createWriteStream = fs.createWriteStream.bind(fs)
fs.createWriteStream = function (path) {
t.ok(false, 'no temporary file should be written')
return _createWriteStream(path)
}
t.equal(fs.existsSync(cachedPrebuild), false, 'nothing cached')
download(opts, function (err) {
t.ok(err, 'should error')
t.equal(fs.existsSync(cachedPrebuild), false, 'nothing cached')
fs.createWriteStream = _createWriteStream
})
})
test('existing host but invalid url should fail', function (t) {
t.plan(3)
var opts = getOpts()
opts.pkg.binary = {
host: 'http://localhost:8888',
remote_path: 'prebuilds',
package_name: 'woohooo-{abi}'
}
var downloadUrl = util.getDownloadUrl(opts)
var cachedPrebuild = util.cachedPrebuild(downloadUrl)
var server = http.createServer(function (req, res) {
t.equal(req.url, '/prebuilds/woohooo-' + process.versions.modules, 'correct url')
res.statusCode = 404
res.end()
}).listen(8888, function () {
download(opts, function (err) {
t.same(err, error.noPrebuilts(opts))
t.equal(fs.existsSync(cachedPrebuild), false, 'nothing cached')
t.end()
server.unref()
})
})
})
test('error during download should fail with no dangling temp file', function (t) {
t.plan(7)
var downloadError = new Error('something went wrong during download')
var opts = getOpts()
opts.pkg.binary = {
host: 'http://localhost:8889',
remote_path: 'prebuilds',
package_name: 'woohooo-{abi}'
}
var downloadUrl = util.getDownloadUrl(opts)
var cachedPrebuild = util.cachedPrebuild(downloadUrl)
var tempFile
var _createWriteStream = fs.createWriteStream.bind(fs)
fs.createWriteStream = function (path) {
tempFile = path
t.ok(/\.tmp$/i.test(path), 'this is the temporary file')
return _createWriteStream(path)
}
var _request = http.request
http.request = function (opts) {
http.request = _request
t.equal('http://' + opts.hostname + ':' + opts.port + opts.path, downloadUrl, 'correct url')
var wrapped = arguments[1]
arguments[1] = function (res) {
t.equal(res.statusCode, 200, 'correct statusCode')
// simulates error during download
setTimeout(function () { res.emit('error', downloadError) }, 10)
wrapped(res)
}
return _request.apply(http, arguments)
}
var server = http.createServer(function (req, res) {
t.equal(req.url, '/prebuilds/woohooo-' + process.versions.modules, 'correct url')
res.statusCode = 200
res.write('yep') // simulates hanging request
}).listen(8889, function () {
download(opts, function (err) {
t.equal(err.message, downloadError.message, 'correct error')
t.equal(fs.existsSync(tempFile), false, 'no dangling temp file')
t.equal(fs.existsSync(cachedPrebuild), false, 'nothing cached')
t.end()
fs.createWriteStream = _createWriteStream
server.unref()
})
})
})
test('should fail if abi is system abi with invalid binary', function (t) {
var opts = getOpts()
opts.abi = rc.abi
opts.pkg.binary = {host: 'http://localhost:8890'}
var server = http.createServer(function (req, res) {
res.statusCode = 200
var archive = path.join(__dirname, 'invalid.tar.gz')
fs.createReadStream(archive).pipe(res)
}).listen(8890, function () {
download(opts, function (err) {
server.unref()
if (err && typeof err.message === 'string') {
t.pass('require failed because of invalid abi')
} else {
t.fail('should have caused a require() error')
}
t.end()
})
})
})
function getOpts () {
return {
pkg: require('a-native-module/package'),
nolocal: true,
platform: process.platform,
arch: process.arch,
path: __dirname,
target: process.version,
log: {http: function (type, message) {}, info: function (type, message) {}}
}
}