| var fs = require('graceful-fs') |
| var path = require('path') |
| |
| var mkdirp = require('mkdirp') |
| var osenv = require('osenv') |
| var rimraf = require('rimraf') |
| var test = require('tap').test |
| |
| var common = require('../common-tap.js') |
| |
| var pkg = path.resolve(__dirname, 'optional-metadep-rollback-collision') |
| var deps = path.resolve(pkg, 'deps') |
| var nm = path.resolve(pkg, 'node_modules') |
| var cache = path.resolve(pkg, 'cache') |
| var pidfile = path.resolve(pkg, 'child.pid') |
| |
| var json = { |
| name: 'optional-metadep-rollback-collision', |
| version: '1.0.0', |
| description: 'let\'s just see about that race condition', |
| optionalDependencies: { |
| opdep: 'file:./deps/opdep' |
| } |
| } |
| |
| var d1 = { |
| name: 'd1', |
| version: '1.0.0', |
| description: 'I FAIL CONSTANTLY', |
| scripts: { |
| preinstall: 'sleep 1' |
| }, |
| dependencies: { |
| foo: 'http://localhost:8080/' |
| } |
| } |
| |
| var d2 = { |
| name: 'd2', |
| version: '1.0.0', |
| description: 'how do you *really* know you exist?', |
| scripts: { |
| postinstall: 'node blart.js' |
| }, |
| dependencies: { |
| 'graceful-fs': '^3.0.2', |
| mkdirp: '^0.5.0', |
| rimraf: '^2.2.8' |
| } |
| } |
| |
| var opdep = { |
| name: 'opdep', |
| version: '1.0.0', |
| description: 'To explode, of course!', |
| main: 'index.js', |
| scripts: { |
| preinstall: 'node bad-server.js' |
| }, |
| dependencies: { |
| d1: 'file:../d1', |
| d2: 'file:../d2' |
| } |
| } |
| |
| |
| var badServer = function () {/* |
| var createServer = require('http').createServer |
| var spawn = require('child_process').spawn |
| var fs = require('fs') |
| var path = require('path') |
| var pidfile = path.resolve(__dirname, '..', '..', 'child.pid') |
| |
| if (process.argv[2]) { |
| console.log('ok') |
| createServer(function (req, res) { |
| setTimeout(function () { |
| res.writeHead(404) |
| res.end() |
| }, 1000) |
| this.close() |
| }).listen(8080) |
| } else { |
| var child = spawn( |
| process.execPath, |
| [__filename, 'whatever'], |
| { |
| stdio: [0, 1, 2], |
| detached: true |
| } |
| ) |
| child.unref() |
| |
| // kill any prior children, if existing. |
| try { |
| var pid = +fs.readFileSync(pidfile) |
| process.kill(pid, 'SIGKILL') |
| } catch (er) {} |
| |
| fs.writeFileSync(pidfile, child.pid + '\n') |
| } |
| */}.toString().split('\n').slice(1, -1).join('\n') |
| |
| var blart = function () {/* |
| var rando = require('crypto').randomBytes |
| var resolve = require('path').resolve |
| |
| var mkdirp = require('mkdirp') |
| var rimraf = require('rimraf') |
| var writeFile = require('graceful-fs').writeFile |
| |
| var BASEDIR = resolve(__dirname, 'arena') |
| |
| var keepItGoingLouder = {} |
| var writers = 0 |
| var errors = 0 |
| |
| function gensym () { return rando(16).toString('hex') } |
| |
| function writeAlmostForever (filename) { |
| if (!keepItGoingLouder[filename]) { |
| writers-- |
| if (writers < 1) return done() |
| } else { |
| writeFile(filename, keepItGoingLouder[filename], function (err) { |
| if (err) errors++ |
| |
| writeAlmostForever(filename) |
| }) |
| } |
| } |
| |
| function done () { |
| rimraf(BASEDIR, function () { |
| if (errors > 0) console.log('not ok - %d errors', errors) |
| else console.log('ok') |
| }) |
| } |
| |
| mkdirp(BASEDIR, function go () { |
| for (var i = 0; i < 16; i++) { |
| var filename = resolve(BASEDIR, gensym() + '.txt') |
| |
| keepItGoingLouder[filename] = '' |
| for (var j = 0; j < 512; j++) keepItGoingLouder[filename] += filename |
| |
| writers++ |
| writeAlmostForever(filename) |
| } |
| |
| setTimeout(function viktor () { |
| // kill all the writers |
| keepItGoingLouder = {} |
| }, 3 * 1000) |
| }) |
| */}.toString().split('\n').slice(1, -1).join('\n') |
| test('setup', function (t) { |
| cleanup() |
| |
| mkdirp.sync(pkg) |
| fs.writeFileSync( |
| path.join(pkg, 'package.json'), |
| JSON.stringify(json, null, 2) |
| ) |
| |
| mkdirp.sync(path.join(deps, 'd1')) |
| fs.writeFileSync( |
| path.join(deps, 'd1', 'package.json'), |
| JSON.stringify(d1, null, 2) |
| ) |
| |
| mkdirp.sync(path.join(deps, 'd2')) |
| fs.writeFileSync( |
| path.join(deps, 'd2', 'package.json'), |
| JSON.stringify(d2, null, 2) |
| ) |
| fs.writeFileSync(path.join(deps, 'd2', 'blart.js'), blart) |
| |
| mkdirp.sync(path.join(deps, 'opdep')) |
| fs.writeFileSync( |
| path.join(deps, 'opdep', 'package.json'), |
| JSON.stringify(opdep, null, 2) |
| ) |
| fs.writeFileSync(path.join(deps, 'opdep', 'bad-server.js'), badServer) |
| |
| t.end() |
| }) |
| |
| test('go go test racer', function (t) { |
| common.npm( |
| [ |
| '--prefix', pkg, |
| '--fetch-retries', '0', |
| '--loglevel', 'silent', |
| '--cache', cache, |
| 'install' |
| ], |
| { |
| cwd: pkg, |
| env: { |
| PATH: process.env.PATH, |
| Path: process.env.Path |
| }, |
| stdio: [0, 'pipe', 2] |
| }, |
| function (er, code, stdout, stderr) { |
| t.ifError(er, 'install ran to completion without error') |
| t.notOk(code, 'npm install exited with code 0') |
| |
| t.equal(stdout, 'ok\nok\n') |
| t.notOk(/not ok/.test(stdout), 'should not contain the string \'not ok\'') |
| t.end() |
| } |
| ) |
| }) |
| |
| test('verify results', function (t) { |
| t.throws(function () { |
| fs.statSync(nm) |
| }) |
| t.end() |
| }) |
| |
| test('cleanup', function (t) { |
| cleanup() |
| t.end() |
| }) |
| |
| function cleanup () { |
| process.chdir(osenv.tmpdir()) |
| try { |
| var pid = +fs.readFileSync(pidfile) |
| process.kill(pid, 'SIGKILL') |
| } catch (er) {} |
| |
| rimraf.sync(pkg) |
| } |