1var t = require('tap') 2var fs = require('fs') 3var path = require('path') 4var fixture = path.resolve(__dirname, 'fixtures') 5var meow = fixture + '/meow.cat' 6var mine = fixture + '/mine.cat' 7var ours = fixture + '/ours.cat' 8var fail = fixture + '/fail.false' 9var noent = fixture + '/enoent.exe' 10var mkdirp = require('mkdirp') 11var rimraf = require('rimraf') 12 13var isWindows = process.platform === 'win32' 14var hasAccess = typeof fs.access === 'function' 15var winSkip = isWindows && 'windows' 16var accessSkip = !hasAccess && 'no fs.access function' 17var hasPromise = typeof Promise === 'function' 18var promiseSkip = !hasPromise && 'no global Promise' 19 20function reset () { 21 delete require.cache[require.resolve('../')] 22 return require('../') 23} 24 25t.test('setup fixtures', function (t) { 26 rimraf.sync(fixture) 27 mkdirp.sync(fixture) 28 fs.writeFileSync(meow, '#!/usr/bin/env cat\nmeow\n') 29 fs.chmodSync(meow, parseInt('0755', 8)) 30 fs.writeFileSync(fail, '#!/usr/bin/env false\n') 31 fs.chmodSync(fail, parseInt('0644', 8)) 32 fs.writeFileSync(mine, '#!/usr/bin/env cat\nmine\n') 33 fs.chmodSync(mine, parseInt('0744', 8)) 34 fs.writeFileSync(ours, '#!/usr/bin/env cat\nours\n') 35 fs.chmodSync(ours, parseInt('0754', 8)) 36 t.end() 37}) 38 39t.test('promise', { skip: promiseSkip }, function (t) { 40 var isexe = reset() 41 t.test('meow async', function (t) { 42 isexe(meow).then(function (is) { 43 t.ok(is) 44 t.end() 45 }) 46 }) 47 t.test('fail async', function (t) { 48 isexe(fail).then(function (is) { 49 t.notOk(is) 50 t.end() 51 }) 52 }) 53 t.test('noent async', function (t) { 54 isexe(noent).catch(function (er) { 55 t.ok(er) 56 t.end() 57 }) 58 }) 59 t.test('noent ignore async', function (t) { 60 isexe(noent, { ignoreErrors: true }).then(function (is) { 61 t.notOk(is) 62 t.end() 63 }) 64 }) 65 t.end() 66}) 67 68t.test('no promise', function (t) { 69 global.Promise = null 70 var isexe = reset() 71 t.throws('try to meow a promise', function () { 72 isexe(meow) 73 }) 74 t.end() 75}) 76 77t.test('access', { skip: accessSkip || winSkip }, function (t) { 78 runTest(t) 79}) 80 81t.test('mode', { skip: winSkip }, function (t) { 82 delete fs.access 83 delete fs.accessSync 84 var isexe = reset() 85 t.ok(isexe.sync(ours, { uid: 0, gid: 0 })) 86 t.ok(isexe.sync(mine, { uid: 0, gid: 0 })) 87 runTest(t) 88}) 89 90t.test('windows', function (t) { 91 global.TESTING_WINDOWS = true 92 var pathExt = '.EXE;.CAT;.CMD;.COM' 93 t.test('pathExt option', function (t) { 94 runTest(t, { pathExt: '.EXE;.CAT;.CMD;.COM' }) 95 }) 96 t.test('pathExt env', function (t) { 97 process.env.PATHEXT = pathExt 98 runTest(t) 99 }) 100 t.test('no pathExt', function (t) { 101 // with a pathExt of '', any filename is fine. 102 // so the "fail" one would still pass. 103 runTest(t, { pathExt: '', skipFail: true }) 104 }) 105 t.test('pathext with empty entry', function (t) { 106 // with a pathExt of '', any filename is fine. 107 // so the "fail" one would still pass. 108 runTest(t, { pathExt: ';' + pathExt, skipFail: true }) 109 }) 110 t.end() 111}) 112 113t.test('cleanup', function (t) { 114 rimraf.sync(fixture) 115 t.end() 116}) 117 118function runTest (t, options) { 119 var isexe = reset() 120 121 var optionsIgnore = Object.create(options || {}) 122 optionsIgnore.ignoreErrors = true 123 124 if (!options || !options.skipFail) { 125 t.notOk(isexe.sync(fail, options)) 126 } 127 t.notOk(isexe.sync(noent, optionsIgnore)) 128 if (!options) { 129 t.ok(isexe.sync(meow)) 130 } else { 131 t.ok(isexe.sync(meow, options)) 132 } 133 134 t.ok(isexe.sync(mine, options)) 135 t.ok(isexe.sync(ours, options)) 136 t.throws(function () { 137 isexe.sync(noent, options) 138 }) 139 140 t.test('meow async', function (t) { 141 if (!options) { 142 isexe(meow, function (er, is) { 143 if (er) { 144 throw er 145 } 146 t.ok(is) 147 t.end() 148 }) 149 } else { 150 isexe(meow, options, function (er, is) { 151 if (er) { 152 throw er 153 } 154 t.ok(is) 155 t.end() 156 }) 157 } 158 }) 159 160 t.test('mine async', function (t) { 161 isexe(mine, options, function (er, is) { 162 if (er) { 163 throw er 164 } 165 t.ok(is) 166 t.end() 167 }) 168 }) 169 170 t.test('ours async', function (t) { 171 isexe(ours, options, function (er, is) { 172 if (er) { 173 throw er 174 } 175 t.ok(is) 176 t.end() 177 }) 178 }) 179 180 if (!options || !options.skipFail) { 181 t.test('fail async', function (t) { 182 isexe(fail, options, function (er, is) { 183 if (er) { 184 throw er 185 } 186 t.notOk(is) 187 t.end() 188 }) 189 }) 190 } 191 192 t.test('noent async', function (t) { 193 isexe(noent, options, function (er, is) { 194 t.ok(er) 195 t.notOk(is) 196 t.end() 197 }) 198 }) 199 200 t.test('noent ignore async', function (t) { 201 isexe(noent, optionsIgnore, function (er, is) { 202 if (er) { 203 throw er 204 } 205 t.notOk(is) 206 t.end() 207 }) 208 }) 209 210 t.test('directory is not executable', function (t) { 211 isexe(__dirname, options, function (er, is) { 212 if (er) { 213 throw er 214 } 215 t.notOk(is) 216 t.end() 217 }) 218 }) 219 220 t.end() 221} 222