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.
 
 
 
 
 
 

163 lines
4.4 KiB

var test = require('tap').test
var assert = require('assert')
var path = require('path')
var requireInject = require('require-inject')
var cache_dir = path.resolve(__dirname, 'correct-mkdir')
test('correct-mkdir: no race conditions', function (t) {
var mock_fs = {}
var did_hook = false
mock_fs.stat = function (path, cb) {
if (path === cache_dir) {
// Return a non-matching owner
cb(null, {
uid: +process.uid + 1,
isDirectory: function () {
return true
}
})
if (!did_hook) {
did_hook = true
doHook()
}
} else {
assert.ok(false, 'Unhandled stat path: ' + path)
}
}
var chown_in_progress = 0
var mock_chownr = function (path, uid, gid, cb) {
++chown_in_progress
process.nextTick(function () {
--chown_in_progress
cb(null)
})
}
var mocks = {
'graceful-fs': mock_fs,
'chownr': mock_chownr
}
var correctMkdir = requireInject('../../lib/utils/correct-mkdir.js', mocks)
var calls_in_progress = 3
function handleCallFinish () {
t.equal(chown_in_progress, 0, 'should not return while chown still in progress')
if (!--calls_in_progress) {
t.end()
}
}
function doHook () {
// This is fired during the first correctMkdir call, after the stat has finished
// but before the chownr has finished
// Buggy old code will fail and return a cached value before initial call is done
correctMkdir(cache_dir, handleCallFinish)
}
// Initial call
correctMkdir(cache_dir, handleCallFinish)
// Immediate call again in case of race condition there
correctMkdir(cache_dir, handleCallFinish)
})
test('correct-mkdir: ignore ENOENTs from chownr', function (t) {
var mock_fs = {}
mock_fs.stat = function (path, cb) {
if (path === cache_dir) {
cb(null, {
isDirectory: function () {
return true
}
})
} else {
assert.ok(false, 'Unhandled stat path: ' + path)
}
}
var mock_chownr = function (path, uid, gid, cb) {
cb({code: 'ENOENT'})
}
var mocks = {
'graceful-fs': mock_fs,
'chownr': mock_chownr
}
var correctMkdir = requireInject('../../lib/utils/correct-mkdir.js', mocks)
function handleCallFinish (err) {
t.ifErr(err, 'chownr\'s ENOENT errors were ignored')
t.end()
}
correctMkdir(cache_dir, handleCallFinish)
})
// NEED TO RUN LAST
// These test checks that Windows users are protected by crashes related to
// unexpectedly having a UID/GID other than 0 if a user happens to add these
// variables to their environment. There are assumptions in correct-mkdir
// that special-case Windows by checking on UID-related things.
test('correct-mkdir: SUDO_UID and SUDO_GID non-Windows', function (t) {
process.env.SUDO_UID = 999
process.env.SUDO_GID = 999
process.getuid = function () { return 0 }
process.getgid = function () { return 0 }
var mock_fs = {}
mock_fs.stat = function (path, cb) {
if (path === cache_dir) {
cb(null, {
uid: 0,
isDirectory: function () {
return true
}
})
} else {
assert.ok(false, 'Unhandled stat path: ' + path)
}
}
var mock_chownr = function (path, uid, gid, cb) {
t.is(uid, +process.env.SUDO_UID, 'using the environment\'s UID')
t.is(gid, +process.env.SUDO_GID, 'using the environment\'s GID')
cb(null, {})
}
var mocks = {
'graceful-fs': mock_fs,
'chownr': mock_chownr
}
var correctMkdir = requireInject('../../lib/utils/correct-mkdir.js', mocks)
function handleCallFinish () {
t.end()
}
correctMkdir(cache_dir, handleCallFinish)
})
test('correct-mkdir: SUDO_UID and SUDO_GID Windows', function (t) {
process.env.SUDO_UID = 999
process.env.SUDO_GID = 999
delete process.getuid
delete process.getgid
var mock_fs = {}
mock_fs.stat = function (path, cb) {
if (path === cache_dir) {
cb(null, {
uid: 0,
isDirectory: function () {
return true
}
})
} else {
assert.ok(false, 'Unhandled stat path: ' + path)
}
}
var mock_chownr = function (path, uid, gid, cb) {
t.fail('chownr should not be called at all on Windows')
cb('nope')
}
var mocks = {
'graceful-fs': mock_fs,
'chownr': mock_chownr
}
var correctMkdir = requireInject('../../lib/utils/correct-mkdir.js', mocks)
function handleCallFinish (err) {
t.ifErr(err, 'chownr was not called because Windows')
t.end()
}
correctMkdir(cache_dir, handleCallFinish)
})