1 /* eslint-disable required-modules */
3 var path = require('path');
4 var fs = require('fs');
5 var assert = require('assert');
6 var os = require('os');
7 var child_process = require('child_process');
8 const stream = require('stream');
9 const util = require('util');
11 const testRoot = path.resolve(process.env.NODE_TEST_DIR ||
12 path.dirname(__filename));
14 exports.testDir = path.dirname(__filename);
15 exports.fixturesDir = path.join(exports.testDir, 'fixtures');
16 exports.libDir = path.join(exports.testDir, '../lib');
17 exports.tmpDirName = 'tmp';
18 exports.PORT = +process.env.NODE_COMMON_PORT || 12346;
19 exports.isWindows = process.platform === 'win32';
20 exports.isAix = process.platform === 'aix';
21 exports.isLinuxPPCBE = (process.platform === 'linux') &&
22 (process.arch === 'ppc64') &&
23 (os.endianness() === 'BE');
24 exports.isSunOS = process.platform === 'sunos';
25 exports.isFreeBSD = process.platform === 'freebsd';
27 exports.enoughTestMem = os.totalmem() > 0x20000000; /* 512MB */
29 function rimrafSync(p) {
31 var st = fs.lstatSync(p);
33 if (e.code === 'ENOENT')
38 if (st && st.isDirectory())
43 if (e.code === 'ENOENT')
45 if (e.code === 'EPERM')
46 return rmdirSync(p, e);
47 if (e.code !== 'EISDIR')
53 function rmdirSync(p, originalEr) {
57 if (e.code === 'ENOTDIR')
59 if (e.code === 'ENOTEMPTY' || e.code === 'EEXIST' || e.code === 'EPERM') {
60 fs.readdirSync(p).forEach(function(f) {
61 rimrafSync(path.join(p, f));
68 exports.refreshTmpDir = function() {
69 rimrafSync(exports.tmpDir);
70 fs.mkdirSync(exports.tmpDir);
73 if (process.env.TEST_THREAD_ID) {
74 exports.PORT += process.env.TEST_THREAD_ID * 100;
75 exports.tmpDirName += '.' + process.env.TEST_THREAD_ID;
77 exports.tmpDir = path.join(testRoot, exports.tmpDirName);
79 var opensslCli = null;
80 var inFreeBSDJail = null;
81 var localhostIPv4 = null;
83 exports.localIPv6Hosts = ['localhost'];
84 if (process.platform === 'linux') {
85 exports.localIPv6Hosts = [
94 // Typically universal
99 Object.defineProperty(exports, 'inFreeBSDJail', {
101 if (inFreeBSDJail !== null) return inFreeBSDJail;
103 if (process.platform === 'freebsd' &&
104 child_process.execSync('sysctl -n security.jail.jailed').toString() ===
106 inFreeBSDJail = true;
108 inFreeBSDJail = false;
110 return inFreeBSDJail;
114 Object.defineProperty(exports, 'localhostIPv4', {
116 if (localhostIPv4 !== null) return localhostIPv4;
118 if (exports.inFreeBSDJail) {
119 // Jailed network interfaces are a bit special - since we need to jump
120 // through loops, as well as this being an exception case, assume the
121 // user will provide this instead.
122 if (process.env.LOCALHOST) {
123 localhostIPv4 = process.env.LOCALHOST;
125 console.error('Looks like we\'re in a FreeBSD Jail. ' +
126 'Please provide your default interface address ' +
127 'as LOCALHOST or expect some tests to fail.');
131 if (localhostIPv4 === null) localhostIPv4 = '127.0.0.1';
133 return localhostIPv4;
137 // opensslCli defined lazily to reduce overhead of spawnSync
138 Object.defineProperty(exports, 'opensslCli', {get: function() {
139 if (opensslCli !== null) return opensslCli;
141 if (process.config.variables.node_shared_openssl) {
142 // use external command
143 opensslCli = 'openssl';
145 // use command built from sources included in Node.js repository
146 opensslCli = path.join(path.dirname(process.execPath), 'openssl-cli');
149 if (exports.isWindows) opensslCli += '.exe';
151 var openssl_cmd = child_process.spawnSync(opensslCli, ['version']);
152 if (openssl_cmd.status !== 0 || openssl_cmd.error !== undefined) {
153 // openssl command cannot be executed
157 }, enumerable: true });
159 Object.defineProperty(exports, 'hasCrypto', {
161 return process.versions.openssl ? true : false;
165 Object.defineProperty(exports, 'hasFipsCrypto', {
167 return process.config.variables.openssl_fips ? true : false;
171 if (exports.isWindows) {
172 exports.PIPE = '\\\\.\\pipe\\libuv-test';
173 if (process.env.TEST_THREAD_ID) {
174 exports.PIPE += '.' + process.env.TEST_THREAD_ID;
177 exports.PIPE = exports.tmpDir + '/test.sock';
180 if (exports.isWindows) {
181 exports.faketimeCli = false;
183 exports.faketimeCli = path.join(__dirname, '..', 'tools', 'faketime', 'src',
187 var ifaces = os.networkInterfaces();
188 exports.hasIPv6 = Object.keys(ifaces).some(function(name) {
189 return /lo/.test(name) && ifaces[name].some(function(info) {
190 return info.family === 'IPv6';
195 exports.ddCommand = function(filename, kilobytes) {
196 if (exports.isWindows) {
197 var p = path.resolve(exports.fixturesDir, 'create-file.js');
198 return '"' + process.argv[0] + '" "' + p + '" "' +
199 filename + '" ' + (kilobytes * 1024);
201 return 'dd if=/dev/zero of="' + filename + '" bs=1024 count=' + kilobytes;
206 exports.spawnCat = function(options) {
207 var spawn = require('child_process').spawn;
209 if (exports.isWindows) {
210 return spawn('more', [], options);
212 return spawn('cat', [], options);
217 exports.spawnSyncCat = function(options) {
218 var spawnSync = require('child_process').spawnSync;
220 if (exports.isWindows) {
221 return spawnSync('more', [], options);
223 return spawnSync('cat', [], options);
228 exports.spawnPwd = function(options) {
229 var spawn = require('child_process').spawn;
231 if (exports.isWindows) {
232 return spawn('cmd.exe', ['/c', 'cd'], options);
234 return spawn('pwd', [], options);
238 exports.platformTimeout = function(ms) {
239 if (process.config.target_defaults.default_configuration === 'Debug')
242 if (process.arch !== 'arm')
245 const armv = process.config.variables.arm_version;
248 return 7 * ms; // ARMv6
251 return 2 * ms; // ARMv7
256 var knownGlobals = [setTimeout,
263 constructor, // Enumerable in V8 3.21.
269 knownGlobals.push(gc);
272 if (global.DTRACE_HTTP_SERVER_RESPONSE) {
273 knownGlobals.push(DTRACE_HTTP_SERVER_RESPONSE);
274 knownGlobals.push(DTRACE_HTTP_SERVER_REQUEST);
275 knownGlobals.push(DTRACE_HTTP_CLIENT_RESPONSE);
276 knownGlobals.push(DTRACE_HTTP_CLIENT_REQUEST);
277 knownGlobals.push(DTRACE_NET_STREAM_END);
278 knownGlobals.push(DTRACE_NET_SERVER_CONNECTION);
281 if (global.COUNTER_NET_SERVER_CONNECTION) {
282 knownGlobals.push(COUNTER_NET_SERVER_CONNECTION);
283 knownGlobals.push(COUNTER_NET_SERVER_CONNECTION_CLOSE);
284 knownGlobals.push(COUNTER_HTTP_SERVER_REQUEST);
285 knownGlobals.push(COUNTER_HTTP_SERVER_RESPONSE);
286 knownGlobals.push(COUNTER_HTTP_CLIENT_REQUEST);
287 knownGlobals.push(COUNTER_HTTP_CLIENT_RESPONSE);
290 if (global.LTTNG_HTTP_SERVER_RESPONSE) {
291 knownGlobals.push(LTTNG_HTTP_SERVER_RESPONSE);
292 knownGlobals.push(LTTNG_HTTP_SERVER_REQUEST);
293 knownGlobals.push(LTTNG_HTTP_CLIENT_RESPONSE);
294 knownGlobals.push(LTTNG_HTTP_CLIENT_REQUEST);
295 knownGlobals.push(LTTNG_NET_STREAM_END);
296 knownGlobals.push(LTTNG_NET_SERVER_CONNECTION);
299 if (global.ArrayBuffer) {
300 knownGlobals.push(ArrayBuffer);
301 knownGlobals.push(Int8Array);
302 knownGlobals.push(Uint8Array);
303 knownGlobals.push(Uint8ClampedArray);
304 knownGlobals.push(Int16Array);
305 knownGlobals.push(Uint16Array);
306 knownGlobals.push(Int32Array);
307 knownGlobals.push(Uint32Array);
308 knownGlobals.push(Float32Array);
309 knownGlobals.push(Float64Array);
310 knownGlobals.push(DataView);
315 knownGlobals.push(Proxy);
319 knownGlobals.push(Symbol);
322 function leakedGlobals() {
325 for (var val in global)
326 if (-1 === knownGlobals.indexOf(global[val]))
331 exports.leakedGlobals = leakedGlobals;
333 // Turn this off if the test should not check for global leaks.
334 exports.globalCheck = true;
336 process.on('exit', function() {
337 if (!exports.globalCheck) return;
338 var leaked = leakedGlobals();
339 if (leaked.length > 0) {
340 console.error('Unknown globals: %s', leaked);
341 assert.ok(false, 'Unknown global found');
346 var mustCallChecks = [];
349 function runCallChecks(exitCode) {
350 if (exitCode !== 0) return;
352 var failed = mustCallChecks.filter(function(context) {
353 return context.actual !== context.expected;
356 failed.forEach(function(context) {
357 console.log('Mismatched %s function calls. Expected %d, actual %d.',
361 console.log(context.stack.split('\n').slice(2).join('\n'));
364 if (failed.length) process.exit(1);
368 exports.mustCall = function(fn, expected) {
369 if (typeof expected !== 'number') expected = 1;
374 stack: (new Error()).stack,
375 name: fn.name || '<anonymous>'
378 // add the exit listener only once to avoid listener leak warnings
379 if (mustCallChecks.length === 0) process.on('exit', runCallChecks);
381 mustCallChecks.push(context);
385 return fn.apply(this, arguments);
389 var etcServicesFileName = path.join('/etc', 'services');
390 if (exports.isWindows) {
391 etcServicesFileName = path.join(process.env.SystemRoot, 'System32', 'drivers',
396 * Returns a string that represents the service name associated
397 * to the service bound to port "port" and using protocol "protocol".
399 * If the service is not defined in the services file, it returns
400 * the port number as a string.
402 * Returns undefined if /etc/services (or its equivalent on non-UNIX
403 * platforms) can't be read.
405 exports.getServiceName = function getServiceName(port, protocol) {
407 throw new Error('Missing port number');
410 if (typeof protocol !== 'string') {
411 throw new Error('Protocol must be a string');
415 * By default, if a service can't be found in /etc/services,
416 * its name is considered to be its port number.
418 var serviceName = port.toString();
421 var servicesContent = fs.readFileSync(etcServicesFileName,
422 { encoding: 'utf8'});
423 var regexp = `^(\\w+)\\s+\\s${port}/${protocol}\\s`;
424 var re = new RegExp(regexp, 'm');
426 var matches = re.exec(servicesContent);
427 if (matches && matches.length > 1) {
428 serviceName = matches[1];
431 console.error('Cannot read file: ', etcServicesFileName);
438 exports.hasMultiLocalhost = function hasMultiLocalhost() {
439 var TCP = process.binding('tcp_wrap').TCP;
441 var ret = t.bind('127.0.0.2', exports.PORT);
446 exports.fileExists = function(pathname) {
448 fs.accessSync(pathname);
455 exports.fail = function(msg) {
456 assert.fail(null, null, msg);
459 // Returns true if the exit code "exitCode" and/or signal name "signal"
460 // represent the exit code and/or signal name of a node process that aborted,
462 exports.nodeProcessAborted = function nodeProcessAborted(exitCode, signal) {
463 // Depending on the compiler used, node will exit with either
464 // exit code 132 (SIGILL), 133 (SIGTRAP) or 134 (SIGABRT).
465 var expectedExitCodes = [132, 133, 134];
467 // On platforms using KSH as the default shell (like SmartOS),
468 // when a process aborts, KSH exits with an exit code that is
469 // greater than 256, and thus the exit code emitted with the 'exit'
470 // event is null and the signal is set to either SIGILL, SIGTRAP,
471 // or SIGABRT (depending on the compiler).
472 const expectedSignals = ['SIGILL', 'SIGTRAP', 'SIGABRT'];
474 // On Windows, v8's base::OS::Abort triggers an access violation,
475 // which corresponds to exit code 3221225477 (0xC0000005)
476 if (process.platform === 'win32')
477 expectedExitCodes = [3221225477];
479 // When using --abort-on-uncaught-exception, V8 will use
480 // base::OS::Abort to terminate the process.
481 // Depending on the compiler used, the shell or other aspects of
482 // the platform used to build the node binary, this will actually
483 // make V8 exit by aborting or by raising a signal. In any case,
484 // one of them (exit code or signal) needs to be set to one of
485 // the expected exit codes or signals.
486 if (signal !== null) {
487 return expectedSignals.indexOf(signal) > -1;
489 return expectedExitCodes.indexOf(exitCode) > -1;
493 // A stream to push an array into a REPL
494 function ArrayStream() {
495 this.run = function(data) {
496 data.forEach((line) => {
497 this.emit('data', line + '\n');
502 util.inherits(ArrayStream, stream.Stream);
503 exports.ArrayStream = ArrayStream;
504 ArrayStream.prototype.readable = true;
505 ArrayStream.prototype.writable = true;
506 ArrayStream.prototype.pause = function() {};
507 ArrayStream.prototype.resume = function() {};
508 ArrayStream.prototype.write = function() {};