-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy pathtest-addon.js
More file actions
159 lines (142 loc) · 5.67 KB
/
Copy pathtest-addon.js
File metadata and controls
159 lines (142 loc) · 5.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
'use strict'
const { describe, it } = require('mocha')
const assert = require('assert')
const path = require('path')
const fs = require('graceful-fs')
const os = require('os')
const cp = require('child_process')
const util = require('../lib/util')
const { platformTimeout } = require('./common')
const addonPath = path.resolve(__dirname, 'node_modules', 'hello_world')
const nodeGyp = path.resolve(__dirname, '..', 'bin', 'node-gyp.js')
const execFileSync = (...args) => cp.execFileSync(...args).toString().trim()
const execFile = async (cmd) => {
const [err, stdout, stderr] = await util.execFile(process.execPath, cmd, {
env: { ...process.env, NODE_GYP_NULL_LOGGER: undefined },
encoding: 'utf-8'
})
return [err, stdout.toString().trim(), stderr.toString().trim().split(/\r?\n/)]
}
function runHello (hostProcess = process.execPath) {
const testCode = "console.log(require('hello_world').hello())"
return execFileSync(hostProcess, ['-e', testCode], { cwd: __dirname })
}
function getEncoding () {
const code = 'import locale;print(locale.getdefaultlocale()[1])'
return execFileSync('python', ['-c', code])
}
function checkCharmapValid () {
try {
const data = execFileSync('python', ['fixtures/test-charmap.py'], { cwd: __dirname })
return data.split('\n').pop() === 'True'
} catch {
return false
}
}
describe('addon', function () {
it('build simple addon', async function () {
this.timeout(platformTimeout(1, { win32: 5 }))
// Set the loglevel otherwise the output disappears when run via 'npm test'
const cmd = [nodeGyp, 'rebuild', '-C', addonPath, '--loglevel=verbose']
const [err, stdout, logLines] = await execFile(cmd)
if (err) {
console.log('-- build stdout (MSBuild/make output) --')
console.log(stdout)
console.log('-- build stderr (gyp logs) --')
console.log(logLines.join('\n'))
}
const lastLine = logLines[logLines.length - 1]
assert.strictEqual(err, null)
assert.strictEqual(lastLine, 'gyp info ok', 'should end in ok')
assert.strictEqual(runHello(), 'world')
})
it('build simple addon in path with non-ascii characters', async function () {
// On cp1252 Windows with UTF-8 mode disabled, the fixture cannot print the
// U+012B in "Latīna" to its stdout pipe, so this guard skips the test.
// Python 3.15 enables UTF-8 mode by default (PEP 686): printing succeeds,
// while getdefaultlocale() still reports cp1252, selecting the Latīna case.
// Python 3.14 with PYTHONUTF8=1 also exercises this previously skipped path.
if (!checkCharmapValid()) {
return this.skip('python console app can\'t encode non-ascii character.')
}
// Select non-ascii characters by current encoding
const testDirName = {
cp936: '文件夹',
cp1252: 'Latīna',
cp932: 'フォルダ'
}[getEncoding()]
// If encoding is UTF-8 or other then no need to test
if (!testDirName) {
return this.skip('no need to test')
}
this.timeout(platformTimeout(1, { win32: 5 }))
let data
const configPath = path.join(addonPath, 'build', 'config.gypi')
try {
data = fs.readFileSync(configPath, 'utf8')
} catch (err) {
return assert.fail(err)
}
const config = JSON.parse(data.replace(/#.+\n/, ''))
const nodeDir = config.variables.nodedir
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'node-gyp-addon-'))
const testDevDir = path.join(tempDir, testDirName)
try {
// The downloaded SDK uses <cache>/<version>/<arch>/node.lib on Windows.
// Passing nodeDir via --nodedir instead selects $(Configuration)/node.lib
// inside that version directory, e.g. Release/node.lib, which is absent.
// --devdir expects the cache root: link nodeDir's parent so node-gyp keeps
// the <version>/<arch>/node.lib layout under the non-ASCII path.
try {
fs.symlinkSync(path.dirname(nodeDir), testDevDir, 'dir')
} catch (err) {
switch (err.code) {
case 'EEXIST': break
case 'EPERM':
return assert.fail(err, null, 'Please try to running console as an administrator')
default:
return assert.fail(err)
}
}
const cmd = [
nodeGyp,
'rebuild',
'-C',
addonPath,
'--loglevel=verbose',
'--devdir=' + testDevDir
]
const [err, stdout, logLines] = await execFile(cmd)
if (err) {
console.log('-- build stdout (MSBuild/make output) --')
console.log(stdout)
console.log('-- build stderr (gyp logs) --')
console.log(logLines.join('\n'))
}
const lastLine = logLines[logLines.length - 1]
assert.strictEqual(err, null)
assert.strictEqual(lastLine, 'gyp info ok', 'should end in ok')
assert.strictEqual(runHello(), 'world')
} finally {
fs.rmSync(tempDir, { recursive: true, force: true })
}
})
it('addon works with renamed host executable', async function () {
this.timeout(platformTimeout(1, { win32: 5 }))
const notNodePath = path.join(os.tmpdir(), 'notnode' + path.extname(process.execPath))
fs.copyFileSync(process.execPath, notNodePath)
const cmd = [nodeGyp, 'rebuild', '-C', addonPath, '--loglevel=verbose']
const [err, stdout, logLines] = await execFile(cmd)
if (err) {
console.log('-- build stdout (MSBuild/make output) --')
console.log(stdout)
console.log('-- build stderr (gyp logs) --')
console.log(logLines.join('\n'))
}
const lastLine = logLines[logLines.length - 1]
assert.strictEqual(err, null)
assert.strictEqual(lastLine, 'gyp info ok', 'should end in ok')
assert.strictEqual(runHello(notNodePath), 'world')
fs.unlinkSync(notNodePath)
})
})