1'use strict' 2 3delete process.env.PYTHON 4 5const test = require('tap').test 6const findPython = require('../lib/find-python') 7const execFile = require('child_process').execFile 8const PythonFinder = findPython.test.PythonFinder 9 10require('npmlog').level = 'warn' 11 12test('find python', function (t) { 13 t.plan(4) 14 15 findPython.test.findPython(null, function (err, found) { 16 t.strictEqual(err, null) 17 var proc = execFile(found, ['-V'], function (err, stdout, stderr) { 18 t.strictEqual(err, null) 19 if (/Python 2/.test(stderr)) { 20 t.strictEqual(stdout, '') 21 t.ok(/Python 2/.test(stderr)) 22 } else { 23 t.ok(/Python 3/.test(stdout)) 24 t.strictEqual(stderr, '') 25 } 26 }) 27 proc.stdout.setEncoding('utf-8') 28 proc.stderr.setEncoding('utf-8') 29 }) 30}) 31 32function poison (object, property) { 33 function fail () { 34 console.error(Error(`Property ${property} should not have been accessed.`)) 35 process.abort() 36 } 37 var descriptor = { 38 configurable: false, 39 enumerable: false, 40 get: fail, 41 set: fail 42 } 43 Object.defineProperty(object, property, descriptor) 44} 45 46function TestPythonFinder () { 47 PythonFinder.apply(this, arguments) 48} 49TestPythonFinder.prototype = Object.create(PythonFinder.prototype) 50// Silence npmlog - remove for debugging 51TestPythonFinder.prototype.log = { 52 silly: () => {}, 53 verbose: () => {}, 54 info: () => {}, 55 warn: () => {}, 56 error: () => {} 57} 58delete TestPythonFinder.prototype.env.NODE_GYP_FORCE_PYTHON 59 60test('find python - python', function (t) { 61 t.plan(6) 62 63 var f = new TestPythonFinder('python', done) 64 f.execFile = function (program, args, opts, cb) { 65 f.execFile = function (program, args, opts, cb) { 66 poison(f, 'execFile') 67 t.strictEqual(program, '/path/python') 68 t.ok(/sys\.version_info/.test(args[1])) 69 cb(null, '2.7.15') 70 } 71 t.strictEqual(program, 72 process.platform === 'win32' ? '"python"' : 'python') 73 t.ok(/sys\.executable/.test(args[1])) 74 cb(null, '/path/python') 75 } 76 f.findPython() 77 78 function done (err, python) { 79 t.strictEqual(err, null) 80 t.strictEqual(python, '/path/python') 81 } 82}) 83 84test('find python - python too old', function (t) { 85 t.plan(2) 86 87 var f = new TestPythonFinder(null, done) 88 f.execFile = function (program, args, opts, cb) { 89 if (/sys\.executable/.test(args[args.length - 1])) { 90 cb(null, '/path/python') 91 } else if (/sys\.version_info/.test(args[args.length - 1])) { 92 cb(null, '2.3.4') 93 } else { 94 t.fail() 95 } 96 } 97 f.findPython() 98 99 function done (err) { 100 t.ok(/Could not find any Python/.test(err)) 101 t.ok(/not supported/i.test(f.errorLog)) 102 } 103}) 104 105test('find python - no python', function (t) { 106 t.plan(2) 107 108 var f = new TestPythonFinder(null, done) 109 f.execFile = function (program, args, opts, cb) { 110 if (/sys\.executable/.test(args[args.length - 1])) { 111 cb(new Error('not found')) 112 } else if (/sys\.version_info/.test(args[args.length - 1])) { 113 cb(new Error('not a Python executable')) 114 } else { 115 t.fail() 116 } 117 } 118 f.findPython() 119 120 function done (err) { 121 t.ok(/Could not find any Python/.test(err)) 122 t.ok(/not in PATH/.test(f.errorLog)) 123 } 124}) 125 126test('find python - no python2, no python, unix', function (t) { 127 t.plan(2) 128 129 var f = new TestPythonFinder(null, done) 130 f.checkPyLauncher = t.fail 131 f.win = false 132 133 f.execFile = function (program, args, opts, cb) { 134 if (/sys\.executable/.test(args[args.length - 1])) { 135 cb(new Error('not found')) 136 } else { 137 t.fail() 138 } 139 } 140 f.findPython() 141 142 function done (err) { 143 t.ok(/Could not find any Python/.test(err)) 144 t.ok(/not in PATH/.test(f.errorLog)) 145 } 146}) 147 148test('find python - no python, use python launcher', function (t) { 149 t.plan(4) 150 151 var f = new TestPythonFinder(null, done) 152 f.win = true 153 154 f.execFile = function (program, args, opts, cb) { 155 if (program === 'py.exe') { 156 t.notEqual(args.indexOf('-2'), -1) 157 t.notEqual(args.indexOf('-c'), -1) 158 return cb(null, 'Z:\\snake.exe') 159 } 160 if (/sys\.executable/.test(args[args.length - 1])) { 161 cb(new Error('not found')) 162 } else if (/sys\.version_info/.test(args[args.length - 1])) { 163 if (program === 'Z:\\snake.exe') { 164 cb(null, '2.7.14') 165 } else { 166 t.fail() 167 } 168 } else { 169 t.fail() 170 } 171 } 172 f.findPython() 173 174 function done (err, python) { 175 t.strictEqual(err, null) 176 t.strictEqual(python, 'Z:\\snake.exe') 177 } 178}) 179 180test('find python - no python, no python launcher, good guess', function (t) { 181 t.plan(4) 182 183 var re = /C:[\\/]Python27[\\/]python[.]exe/ 184 var f = new TestPythonFinder(null, done) 185 f.win = true 186 187 f.execFile = function (program, args, opts, cb) { 188 if (program === 'py.exe') { 189 f.execFile = function (program, args, opts, cb) { 190 poison(f, 'execFile') 191 t.ok(re.test(program)) 192 t.ok(/sys\.version_info/.test(args[args.length - 1])) 193 cb(null, '2.7.14') 194 } 195 return cb(new Error('not found')) 196 } 197 if (/sys\.executable/.test(args[args.length - 1])) { 198 cb(new Error('not found')) 199 } else { 200 t.fail() 201 } 202 } 203 f.findPython() 204 205 function done (err, python) { 206 t.strictEqual(err, null) 207 t.ok(re.test(python)) 208 } 209}) 210 211test('find python - no python, no python launcher, bad guess', function (t) { 212 t.plan(2) 213 214 var f = new TestPythonFinder(null, done) 215 f.win = true 216 217 f.execFile = function (program, args, opts, cb) { 218 if (/sys\.executable/.test(args[args.length - 1])) { 219 cb(new Error('not found')) 220 } else if (/sys\.version_info/.test(args[args.length - 1])) { 221 cb(new Error('not a Python executable')) 222 } else { 223 t.fail() 224 } 225 } 226 f.findPython() 227 228 function done (err) { 229 t.ok(/Could not find any Python/.test(err)) 230 t.ok(/not in PATH/.test(f.errorLog)) 231 } 232}) 233