1 var path = require('path');
2 var fs = require('fs');
3 var assert = require('assert');
4 var os = require('os');
6 exports.testDir = path.dirname(__filename);
7 exports.fixturesDir = path.join(exports.testDir, 'fixtures');
8 exports.libDir = path.join(exports.testDir, '../lib');
9 exports.tmpDirName = 'tmp';
10 exports.PORT = +process.env.NODE_COMMON_PORT || 12346;
12 if (process.env.TEST_THREAD_ID) {
13 // Distribute ports in parallel tests
14 if (!process.env.NODE_COMMON_PORT)
15 exports.PORT += +process.env.TEST_THREAD_ID * 100;
17 exports.tmpDirName += '.' + process.env.TEST_THREAD_ID;
19 exports.tmpDir = path.join(exports.testDir, exports.tmpDirName);
21 exports.opensslCli = path.join(path.dirname(process.execPath), 'openssl-cli');
22 if (process.platform === 'win32') {
23 exports.PIPE = '\\\\.\\pipe\\libuv-test';
24 exports.opensslCli += '.exe';
26 exports.PIPE = exports.tmpDir + '/test.sock';
29 if (process.env.NODE_COMMON_PIPE) {
30 exports.PIPE = process.env.NODE_COMMON_PIPE;
31 // Remove manually, the test runner won't do it
32 // for us like it does for files in test/tmp.
34 fs.unlinkSync(exports.PIPE);
41 fs.accessSync(exports.opensslCli);
43 exports.opensslCli = false;
46 if (process.platform === 'win32') {
47 exports.faketimeCli = false;
49 exports.faketimeCli = path.join(__dirname, "..", "tools", "faketime", "src",
53 var ifaces = os.networkInterfaces();
54 exports.hasIPv6 = Object.keys(ifaces).some(function(name) {
55 return /lo/.test(name) && ifaces[name].some(function(info) {
56 return info.family === 'IPv6';
60 var util = require('util');
61 for (var i in util) exports[i] = util[i];
62 //for (var i in exports) global[i] = exports[i];
64 function protoCtrChain(o) {
66 for (; o; o = o.__proto__) { result.push(o.constructor); }
70 exports.indirectInstanceOf = function(obj, cls) {
71 if (obj instanceof cls) { return true; }
72 var clsChain = protoCtrChain(cls.prototype);
73 var objChain = protoCtrChain(obj);
74 return objChain.slice(-clsChain.length) === clsChain;
78 exports.ddCommand = function(filename, kilobytes) {
79 if (process.platform === 'win32') {
80 var p = path.resolve(exports.fixturesDir, 'create-file.js');
81 return '"' + process.argv[0] + '" "' + p + '" "' +
82 filename + '" ' + (kilobytes * 1024);
84 return 'dd if=/dev/zero of="' + filename + '" bs=1024 count=' + kilobytes;
89 exports.spawnCat = function(options) {
90 var spawn = require('child_process').spawn;
92 if (process.platform === 'win32') {
93 return spawn('more', [], options);
95 return spawn('cat', [], options);
100 exports.spawnSyncCat = function(options) {
101 var spawnSync = require('child_process').spawnSync;
103 if (process.platform === 'win32') {
104 return spawnSync('more', [], options);
106 return spawnSync('cat', [], options);
111 exports.spawnPwd = function(options) {
112 var spawn = require('child_process').spawn;
114 if (process.platform === 'win32') {
115 return spawn('cmd.exe', ['/c', 'cd'], options);
117 return spawn('pwd', [], options);
121 var knownGlobals = [setTimeout,
128 constructor, // Enumerable in V8 3.21.
134 knownGlobals.push(gc);
137 if (global.DTRACE_HTTP_SERVER_RESPONSE) {
138 knownGlobals.push(DTRACE_HTTP_SERVER_RESPONSE);
139 knownGlobals.push(DTRACE_HTTP_SERVER_REQUEST);
140 knownGlobals.push(DTRACE_HTTP_CLIENT_RESPONSE);
141 knownGlobals.push(DTRACE_HTTP_CLIENT_REQUEST);
142 knownGlobals.push(DTRACE_NET_STREAM_END);
143 knownGlobals.push(DTRACE_NET_SERVER_CONNECTION);
146 if (global.COUNTER_NET_SERVER_CONNECTION) {
147 knownGlobals.push(COUNTER_NET_SERVER_CONNECTION);
148 knownGlobals.push(COUNTER_NET_SERVER_CONNECTION_CLOSE);
149 knownGlobals.push(COUNTER_HTTP_SERVER_REQUEST);
150 knownGlobals.push(COUNTER_HTTP_SERVER_RESPONSE);
151 knownGlobals.push(COUNTER_HTTP_CLIENT_REQUEST);
152 knownGlobals.push(COUNTER_HTTP_CLIENT_RESPONSE);
155 if (global.ArrayBuffer) {
156 knownGlobals.push(ArrayBuffer);
157 knownGlobals.push(Int8Array);
158 knownGlobals.push(Uint8Array);
159 knownGlobals.push(Uint8ClampedArray);
160 knownGlobals.push(Int16Array);
161 knownGlobals.push(Uint16Array);
162 knownGlobals.push(Int32Array);
163 knownGlobals.push(Uint32Array);
164 knownGlobals.push(Float32Array);
165 knownGlobals.push(Float64Array);
166 knownGlobals.push(DataView);
171 knownGlobals.push(Proxy);
175 knownGlobals.push(Symbol);
178 function leakedGlobals() {
181 for (var val in global)
182 if (-1 === knownGlobals.indexOf(global[val]))
187 exports.leakedGlobals = leakedGlobals;
189 // Turn this off if the test should not check for global leaks.
190 exports.globalCheck = true;
192 process.on('exit', function() {
193 if (!exports.globalCheck) return;
194 var leaked = leakedGlobals();
195 if (leaked.length > 0) {
196 console.error('Unknown globals: %s', leaked);
197 assert.ok(false, 'Unknown global found');
202 var mustCallChecks = [];
205 function runCallChecks(exitCode) {
206 if (exitCode !== 0) return;
208 var failed = mustCallChecks.filter(function(context) {
209 return context.actual !== context.expected;
212 failed.forEach(function(context) {
213 console.log('Mismatched %s function calls. Expected %d, actual %d.',
217 console.log(context.stack.split('\n').slice(2).join('\n'));
220 if (failed.length) process.exit(1);
224 exports.mustCall = function(fn, expected) {
225 if (typeof expected !== 'number') expected = 1;
230 stack: (new Error).stack,
231 name: fn.name || '<anonymous>'
234 // add the exit listener only once to avoid listener leak warnings
235 if (mustCallChecks.length === 0) process.on('exit', runCallChecks);
237 mustCallChecks.push(context);
241 return fn.apply(this, arguments);
245 exports.checkSpawnSyncRet = function(ret) {
246 assert.strictEqual(ret.status, 0);
247 assert.strictEqual(ret.error, undefined);
250 var etcServicesFileName = path.join('/etc', 'services');
251 if (process.platform === 'win32') {
252 etcServicesFileName = path.join(process.env.SystemRoot, 'System32', 'drivers',
257 * Returns a string that represents the service name associated
258 * to the service bound to port "port" and using protocol "protocol".
260 * If the service is not defined in the services file, it returns
261 * the port number as a string.
263 * Returns undefined if /etc/services (or its equivalent on non-UNIX
264 * platforms) can't be read.
266 exports.getServiceName = function getServiceName(port, protocol) {
268 throw new Error("Missing port number");
271 if (typeof protocol !== 'string') {
272 throw new Error("Protocol must be a string");
276 * By default, if a service can't be found in /etc/services,
277 * its name is considered to be its port number.
279 var serviceName = port.toString();
283 * I'm not a big fan of readFileSync, but reading /etc/services asynchronously
284 * here would require implementing a simple line parser, which seems overkill
285 * for a simple utility function that is not running concurrently with any
288 var servicesContent = fs.readFileSync(etcServicesFileName,
289 { encoding: 'utf8'});
290 var regexp = util.format('^(\\w+)\\s+\\s%d/%s\\s', port, protocol);
291 var re = new RegExp(regexp, 'm');
293 var matches = re.exec(servicesContent);
294 if (matches && matches.length > 1) {
295 serviceName = matches[1];
298 console.error('Cannot read file: ', etcServicesFileName);
305 exports.hasMultiLocalhost = function hasMultiLocalhost() {
306 var TCP = process.binding('tcp_wrap').TCP;
308 var ret = t.bind('127.0.0.2', exports.PORT);
313 exports.isValidHostname = function(str) {
314 // See http://stackoverflow.com/a/3824105
316 '^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])' +
317 '(\\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]))*$');
319 return !!str.match(re) && str.length <= 255;
322 exports.fileExists = function(pathname) {
324 fs.accessSync(pathname);