1var fs = require('fs') 2var lockFile = require('../') 3var test = require('tap').test 4var path = require('path') 5var lock = path.resolve(__dirname, 'stale.lock') 6var touch = require('touch') 7var spawn = require('child_process').spawn 8var node = process.execPath 9 10// We're using a lockfile with an artificially old date, 11// so make it use that instead of ctime. 12// Probably you should never do this in production! 13lockFile.filetime = 'mtime' 14 15if (process.argv[2] === 'child') { 16 return child() 17} 18 19function child () { 20 // Make fs.stat take 100ms to return its data 21 // This is important because, in a test scenario where 22 // we're statting the same exact file rapid-fire like this, 23 // it'll end up being cached by the FS, and never trigger 24 // the race condition we're trying to expose. 25 fs.stat = function (stat) { return function () { 26 var args = [].slice.call(arguments) 27 var cb = args.pop() 28 stat.apply(fs, args.concat(function(er, st) { 29 setTimeout(function () { 30 cb(er, st) 31 }, 100) 32 })) 33 }}(fs.stat) 34 35 lockFile.lock(lock, { stale: 100000 }, function (er) { 36 if (er && er.code !== 'EEXIST') 37 throw er 38 else if (er) 39 process.exit(17) 40 else 41 setTimeout(function(){}, 500) 42 }) 43} 44 45test('create stale file', function (t) { 46 try { fs.unlinkSync(lock) } catch (er) {} 47 touch.sync(lock, { time: '1979-07-01T19:10:00.000Z' }) 48 t.end() 49}) 50 51test('contenders', function (t) { 52 var n = 10 53 var fails = 0 54 var wins = 0 55 var args = [ __filename, 'child' ] 56 var opt = { stdio: [0, "pipe", 2] } 57 for (var i = 0; i < n; i++) { 58 spawn(node, args, opt).on('close', then) 59 } 60 61 function then (code) { 62 if (code === 17) { 63 fails ++ 64 } else if (code) { 65 t.fail("unexpected failure", code) 66 fails ++ 67 } else { 68 wins ++ 69 } 70 if (fails + wins === n) { 71 done() 72 } 73 } 74 75 function done () { 76 t.equal(wins, 1, "should have 1 lock winner") 77 t.equal(fails, n - 1, "all others should lose") 78 t.end() 79 } 80}) 81 82test('remove stale file', function (t) { 83 try { fs.unlinkSync(lock) } catch (er) {} 84 t.end() 85}) 86