diff --git a/README.md b/README.md
index 7dbe826..5fd5831 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# string_decoder
-***Node-core v7.0.0 string_decoder for userland***
+***Node-core v8.9.4 string_decoder for userland***
[![NPM](https://nodei.co/npm/string_decoder.png?downloads=true&downloadRank=true)](https://nodei.co/npm/string_decoder/)
@@ -15,7 +15,7 @@ npm install --save string_decoder
This package is a mirror of the string_decoder implementation in Node-core.
-Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v7.8.0/docs/api/).
+Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v8.9.4/docs/api/).
As of version 1.0.0 **string_decoder** uses semantic versioning.
diff --git a/build/build.js b/build/build.js
index f52fd28..52dd130 100755
--- a/build/build.js
+++ b/build/build.js
@@ -16,7 +16,7 @@ const hyperquest = require('hyperquest')
, nodeVersionRegexString = '\\d+\\.\\d+\\.\\d+'
, usageVersionRegex = RegExp('^' + nodeVersionRegexString + '$')
, readmeVersionRegex =
- RegExp('((?:Node-core )|(?:https\:\/\/nodejs\.org\/dist\/)v)' + nodeVersionRegexString, 'g')
+ RegExp('((?:(?:Node-core )|(?:https\:\/\/nodejs\.org\/dist\/))v)' + nodeVersionRegexString, 'g')
, readmePath = path.join(__dirname, '..', 'README.md')
, files = require('./files')
@@ -49,21 +49,37 @@ function processFile (inputLoc, out, replacements) {
var arg2 = replacement[1]
if (typeof arg2 === 'function')
arg2 = arg2.bind(data)
+ if (arg2 === undefined) {
+ console.error('missing second arg for file', inputLoc, replacement)
+ throw new Error('missing second arg in replacement')
+ }
data = data.replace(regexp, arg2)
})
if (inputLoc.slice(-3) === '.js') {
- const transformed = babel.transform(data, {
- plugins: [
- 'transform-es2015-parameters',
- 'transform-es2015-arrow-functions',
- 'transform-es2015-block-scoping',
- 'transform-es2015-template-literals',
- 'transform-es2015-shorthand-properties',
- 'transform-es2015-for-of',
- 'transform-es2015-destructuring'
- ]
- })
- data = transformed.code
+ try {
+ const transformed = babel.transform(data, {
+ plugins: [
+ 'transform-es2015-parameters',
+ 'transform-es2015-arrow-functions',
+ 'transform-es2015-block-scoping',
+ 'transform-es2015-template-literals',
+ 'transform-es2015-shorthand-properties',
+ 'transform-es2015-for-of',
+ ['transform-es2015-classes', { loose: true }],
+ 'transform-es2015-destructuring',
+ 'transform-es2015-computed-properties',
+ 'transform-es2015-spread'
+ ]
+ })
+ data = transformed.code
+ } catch (err) {
+ fs.writeFile(out + '.errored.js', data, encoding, function () {
+ console.log('Wrote errored', out)
+
+ throw err
+ })
+ return
+ }
}
fs.writeFile(out, data, encoding, function (err) {
if (err) throw err
@@ -112,7 +128,6 @@ pump(
throw err
}
-
//--------------------------------------------------------------------
// Grab & process files in ../lib/
@@ -137,15 +152,23 @@ pump(
//--------------------------------------------------------------------
// Grab the nodejs/node test/common.js
- processFile(
- testsrcurl.replace(/parallel\/$/, 'common.js')
- , path.join(testourroot, '../common.js')
- , testReplace['common.js']
- )
+ glob(path.join(src, 'test/common/*'), function (err, list) {
+ if (err) {
+ throw err
+ }
+
+ list.forEach(function (file) {
+ file = path.basename(file)
+ processFile(
+ path.join(testsrcurl.replace(/parallel\/$/, 'common/'), file)
+ , path.join(testourroot.replace('parallel', 'common'), file)
+ , testReplace['common.js']
+ )
+ })
+ })
//--------------------------------------------------------------------
// Update Node version in README
-
processFile(readmePath, readmePath, [
[readmeVersionRegex, "$1" + nodeVersion]
])
diff --git a/build/common-replacements.js b/build/common-replacements.js
new file mode 100644
index 0000000..e17f5d7
--- /dev/null
+++ b/build/common-replacements.js
@@ -0,0 +1,59 @@
+module.exports.altForEachImplReplacement = [
+ /$/
+ , '\nfunction forEach (xs, f) {\n'
+ + ' for (var i = 0, l = xs.length; i < l; i++) {\n'
+ + ' f(xs[i], i);\n'
+ + ' }\n'
+ + '}\n'
+]
+
+module.exports.altForEachUseReplacement = [
+ /(\W)([\w\.\(\),\[\] ']+)(\.forEach\()/gm
+ , '$1forEach($2, '
+]
+
+module.exports.specialForEachReplacment = [
+ /(\W)(\[(?:\d\,\s)+\d\])(\.forEach\()/gm
+ , '$1forEach($2, '
+]
+
+module.exports.altIndexOfImplReplacement = [
+ /$/
+ , '\nfunction indexOf (xs, x) {\n'
+ + ' for (var i = 0, l = xs.length; i < l; i++) {\n'
+ + ' if (xs[i] === x) return i;\n'
+ + ' }\n'
+ + ' return -1;\n'
+ + '}\n'
+]
+
+module.exports.altIndexOfUseReplacement = [
+ /(\W)([\w\.\(\),\[\]]+)(\.indexOf\()/gm
+ , '$1indexOf($2, '
+]
+module.exports.objectKeysDefine = [
+ /^('use strict';)$/m
+ , '$1\n\n/**/\nvar objectKeys = Object.keys || function (obj) {\n'
+ + ' var keys = [];\n'
+ + ' for (var key in obj) keys.push(key);\n'
+ + ' return keys;\n'
+ + '}\n/**/\n'
+]
+
+module.exports.objectKeysReplacement = [
+ /Object\.keys/g
+ , 'objectKeys'
+ ]
+
+
+module.exports.bufferShimFix = [
+ /^('use strict';)$/m,
+ `/**/
+ const bufferShim = require('safe-buffer').Buffer;
+ /**/`
+]
+
+module.exports.bufferStaticMethods = [
+ /Buffer\.((?:alloc)|(?:allocUnsafe)|(?:from))/g,
+ `bufferShim.$1`
+]
diff --git a/build/files.js b/build/files.js
index 66f195d..ff6b7c6 100644
--- a/build/files.js
+++ b/build/files.js
@@ -15,8 +15,11 @@ module.exports['string_decoder.js'] = [
]
, [
- /const Buffer = require\('buffer'\).Buffer;/
- , 'var Buffer = require(\'safe-buffer\').Buffer;\n'
+ /(?:var|const) (?:{ )Buffer(?: }) = require\('buffer'\)(?:\.Buffer)?;/,
+ `/**/
+ var Buffer = require('safe-buffer').Buffer;
+/**/
+`
]
// add Buffer.isEncoding where missing
diff --git a/build/package.json b/build/package.json
index 29dc1c2..cf2a769 100644
--- a/build/package.json
+++ b/build/package.json
@@ -1,23 +1,26 @@
{
- "name": "string_decoder-build",
+ "name": "readable-stream-build",
"version": "0.0.0",
"description": "",
"main": "build.js",
"dependencies": {
- "babel-core": "^6.5.2",
+ "babel-core": "^6.26.0",
"babel-plugin-transform-es2015-arrow-functions": "^6.5.2",
- "babel-plugin-transform-es2015-block-scoping": "^6.5.0",
+ "babel-plugin-transform-es2015-block-scoping": "^6.26.0",
+ "babel-plugin-transform-es2015-classes": "^6.24.1",
+ "babel-plugin-transform-es2015-computed-properties": "^6.24.1",
"babel-plugin-transform-es2015-destructuring": "^6.18.0",
"babel-plugin-transform-es2015-for-of": "^6.8.0",
- "babel-plugin-transform-es2015-parameters": "^6.11.4",
- "babel-plugin-transform-es2015-shorthand-properties": "^6.8.0",
+ "babel-plugin-transform-es2015-parameters": "^6.24.1",
+ "babel-plugin-transform-es2015-shorthand-properties": "^6.24.1",
+ "babel-plugin-transform-es2015-spread": "^6.22.0",
"babel-plugin-transform-es2015-template-literals": "^6.8.0",
- "bl": "^1.2.0",
- "glob": "^7.1.1",
- "gunzip-maybe": "^1.4.0",
- "hyperquest": "^2.1.2",
- "pump": "^1.0.2",
- "rimraf": "^2.6.1",
- "tar-fs": "^1.15.1"
+ "bl": "^1.2.1",
+ "glob": "^7.1.2",
+ "gunzip-maybe": "^1.4.1",
+ "hyperquest": "^2.1.3",
+ "pump": "^3.0.0",
+ "rimraf": "^2.6.2",
+ "tar-fs": "^1.16.0"
}
}
diff --git a/build/test-replacements.js b/build/test-replacements.js
index 11b1bb0..830dbca 100644
--- a/build/test-replacements.js
+++ b/build/test-replacements.js
@@ -1,3 +1,8 @@
+const altForEachImplReplacement = require('./common-replacements').altForEachImplReplacement
+ , altForEachUseReplacement = require('./common-replacements').altForEachUseReplacement
+ , objectKeysDefine = require('./common-replacements').objectKeysDefine
+ , objectKeysReplacement = require('./common-replacements').objectKeysReplacement
+
module.exports.all = [
[
/require\(['"]string_decoder['"]\)/g
@@ -16,27 +21,57 @@ module.exports.all = [
]
-module.exports['common.js'] = [
+
+module.exports['test-string-decoder.js'] = [
+ // test removed because it is V8-version dependant.
[
- /^ setImmediate,$/m
- , ' typeof setImmediate == \'undefined\' ? null : setImmediate,'
+ /test\('utf-8', bufferShim\.from\('EDA0B5EDB08D'.*\n.*\n/
+ , ''
+ ],
+ , [
+ /test\('utf-8', bufferShim\.from\('F0B841', 'hex'.*\n/
+ , ''
]
-
, [
- /^ clearImmediate,$/m
- , ' typeof clearImmediate == \'undefined\' ? null : clearImmediate,'
+ /test\('utf-8', bufferShim\.from\('CCE2B8B8', 'hex'.*\n/
+ , ''
+ ]
+ , [
+ /test\('utf-8', bufferShim\.from\('E2B8CCB8', 'hex'.*\n/
+ , ''
]
-
, [
- /^ global];$/m
- , ' global].filter(Boolean);'
+ /assert\.strictEqual\(decoder\.end(), '\ufffd'\);\n/
+ , ''
]
+]
+
+module.exports['common.js'] = [
+ objectKeysDefine
+ , objectKeysReplacement
+ , altForEachImplReplacement
+ , altForEachUseReplacement
, [
- /^/
- , 'require(\'babel-polyfill\');'
+ /(exports.mustCall[\s\S]*)/m
+ , '$1\n'
+ + 'if (!util._errnoException) {\n'
+ + ' var uv;\n'
+ + ' util._errnoException = function(err, syscall) {\n'
+ + ' if (util.isUndefined(uv)) try { uv = process.binding(\'uv\'); } catch (e) {}\n'
+ + ' var errname = uv ? uv.errname(err) : \'\';\n'
+ + ' var e = new Error(syscall + \' \' + errname);\n'
+ + ' e.code = errname;\n'
+ + ' e.errno = errname;\n'
+ + ' e.syscall = syscall;\n'
+ + ' return e;\n'
+ + ' };\n'
+ + '}\n'
]
+ // for streams2 on node 0.11
+ // and dtrace in 0.10
+ // and coverage in all
, [
/^( for \(var x in global\) \{|function leakedGlobals\(\) \{)$/m
, ' /**/\n'
@@ -51,12 +86,89 @@ module.exports['common.js'] = [
+ '\'core,__core-js_shared__,Promise,Map,Set,WeakMap,WeakSet,Reflect,System,asap,Observable,regeneratorRuntime,_babelPolyfill\'.split(\',\').filter(function (item) { return typeof global[item] !== undefined}).forEach(function (item) {knownGlobals.push(global[item])})'
+ ' /**/\n\n$1'
]
-]
-module.exports['test-string-decoder.js'] = [
- // test removed because it is V8-version dependant.
- [
- /test\('utf-8', bufferShim.from\('EDA0B5EDB08D'.*\n.*\n/
- , ''
+ // for node 0.8
+ , [
+ /^/
+ , '/**/'
+ + '\nif (!global.setImmediate) {\n'
+ + ' global.setImmediate = function setImmediate(fn) {\n'
+
+ + ' return setTimeout(fn.bind.apply(fn, arguments), 4);\n'
+ + ' };\n'
+ + '}\n'
+ + 'if (!global.clearImmediate) {\n'
+ + ' global.clearImmediate = function clearImmediate(i) {\n'
+ + ' return clearTimeout(i);\n'
+ + ' };\n'
+ + '}\n'
+ + '/**/\n'
+ ]
+ , [
+ /^if \(global\.ArrayBuffer\) \{([^\}]+)\}$/m
+ , '/**/if (!process.browser) {'
+ + '\nif \(global\.ArrayBuffer\) {$1}\n'
+ + '}/**/\n'
+ ]
+ , [
+ /^Object\.defineProperty\(([\w\W]+?)\}\)\;/mg
+ , '/**/if (!process.browser) {'
+ + '\nObject\.defineProperty($1});\n'
+ + '}/**/\n'
+ ]
+ , [
+ /if \(!process\.send\)/
+ , 'if (!process.send && !process.browser)'
]
+ , [
+ /^/,
+ `/**/
+ require('babel-polyfill');
+ var util = require('util');
+ for (var i in util) exports[i] = util[i];
+ /**/`
+ ],
+ [
+ /var regexp = `\^\(\\\\w\+\)\\\\s\+\\\\s\$\{port\}\/\$\{protocol\}\\\\s`;/,
+ `var regexp = '^(\\w+)\\s+\\s' + port + '/' + protocol + '\\s';`
+ ],
+ [
+ /^var util = require\('util'\);/m
+ , '\n/**/\nvar util = require(\'core-util-is\');\n'
+ + 'util.inherits = require(\'inherits\');\n/**/\n'
+ ],
+ [
+ /^const util = require\('util'\);/m
+, '\n/**/\nvar util = require(\'core-util-is\');\n'
+ + 'util.inherits = require(\'inherits\');\n/**/\n'
+]
+, [
+ /process\.binding\('timer_wrap'\)\.Timer;/,
+ '{now: function (){}}'
+],
+[
+ /(exports\.enoughTestCpu[^;]+;)/,
+ '/*$1*/'
+],
+[
+ /exports\.buildType/,
+ '//exports.buildType'
+],
+[
+ /require\('async_hooks'\)/,
+ '/*require(\'async_hooks\')'
+],
+[
+ /\}\).enable\(\);/,
+ '}).enable();*/'
+],
+[
+ /(?:var|const) async_wrap = process\.binding\('async_wrap'\);\n.*(?:var|const) (?:{ )?kCheck(?: })? = async_wrap\.constants(?:\.kCheck)?;/gm,
+ '// const async_wrap = process.binding(\'async_wrap\');\n' +
+ ' // const kCheck = async_wrap.constants.kCheck;'
+],
+[
+ /async_wrap\.async_hook_fields\[kCheck\] \+= 1;/,
+ '// async_wrap.async_hook_fields[kCheck] += 1;'
+]
]
diff --git a/lib/string_decoder.js b/lib/string_decoder.js
index 26fb94c..2e89e63 100644
--- a/lib/string_decoder.js
+++ b/lib/string_decoder.js
@@ -1,6 +1,30 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
'use strict';
+/**/
+
var Buffer = require('safe-buffer').Buffer;
+/**/
var isEncoding = Buffer.isEncoding || function (encoding) {
encoding = '' + encoding;
@@ -112,10 +136,10 @@ StringDecoder.prototype.fillLast = function (buf) {
};
// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a
-// continuation byte.
+// continuation byte. If an invalid byte is detected, -2 is returned.
function utf8CheckByte(byte) {
if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4;
- return -1;
+ return byte >> 6 === 0x02 ? -1 : -2;
}
// Checks at most 3 bytes at the end of a Buffer in order to detect an
@@ -129,13 +153,13 @@ function utf8CheckIncomplete(self, buf, i) {
if (nb > 0) self.lastNeed = nb - 1;
return nb;
}
- if (--j < i) return 0;
+ if (--j < i || nb === -2) return 0;
nb = utf8CheckByte(buf[j]);
if (nb >= 0) {
if (nb > 0) self.lastNeed = nb - 2;
return nb;
}
- if (--j < i) return 0;
+ if (--j < i || nb === -2) return 0;
nb = utf8CheckByte(buf[j]);
if (nb >= 0) {
if (nb > 0) {
@@ -149,7 +173,7 @@ function utf8CheckIncomplete(self, buf, i) {
// Validates as many continuation bytes for a multi-byte UTF-8 character as
// needed or are available. If we see a non-continuation byte where we expect
// one, we "replace" the validated continuation bytes we've seen so far with
-// UTF-8 replacement characters ('\ufffd'), to match v8's UTF-8 decoding
+// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding
// behavior. The continuation byte check is included three times in the case
// where all of the continuation bytes for a character exist in the same buffer.
// It is also done this way as a slight performance increase instead of using a
@@ -157,17 +181,17 @@ function utf8CheckIncomplete(self, buf, i) {
function utf8CheckExtraBytes(self, buf, p) {
if ((buf[0] & 0xC0) !== 0x80) {
self.lastNeed = 0;
- return '\ufffd'.repeat(p);
+ return '\ufffd';
}
if (self.lastNeed > 1 && buf.length > 1) {
if ((buf[1] & 0xC0) !== 0x80) {
self.lastNeed = 1;
- return '\ufffd'.repeat(p + 1);
+ return '\ufffd';
}
if (self.lastNeed > 2 && buf.length > 2) {
if ((buf[2] & 0xC0) !== 0x80) {
self.lastNeed = 2;
- return '\ufffd'.repeat(p + 2);
+ return '\ufffd';
}
}
}
@@ -198,11 +222,11 @@ function utf8Text(buf, i) {
return buf.toString('utf8', i, end);
}
-// For UTF-8, a replacement character for each buffered byte of a (partial)
-// character needs to be added to the output.
+// For UTF-8, a replacement character is added when ending on a partial
+// character.
function utf8End(buf) {
var r = buf && buf.length ? this.write(buf) : '';
- if (this.lastNeed) return r + '\ufffd'.repeat(this.lastTotal - this.lastNeed);
+ if (this.lastNeed) return r + '\ufffd';
return r;
}
diff --git a/package.json b/package.json
index 49408e8..c359e28 100644
--- a/package.json
+++ b/package.json
@@ -8,10 +8,13 @@
},
"devDependencies": {
"babel-polyfill": "^6.23.0",
+ "core-util-is": "^1.0.2",
+ "inherits": "^2.0.3",
"tap": "~0.4.8"
},
"scripts": {
- "test": "tap test/parallel/*.js && node test/verify-dependencies"
+ "test": "tap test/parallel/*.js && node test/verify-dependencies",
+ "ci": "tap test/parallel/*.js test/ours/*.js --tap | tee test.tap && node test/verify-dependencies.js"
},
"repository": {
"type": "git",
diff --git a/test/common.js b/test/common.js
deleted file mode 100644
index e879f8e..0000000
--- a/test/common.js
+++ /dev/null
@@ -1,583 +0,0 @@
-require('babel-polyfill'); /* eslint-disable required-modules */
-'use strict';
-var path = require('path');
-var fs = require('fs');
-var assert = require('assert');
-var os = require('os');
-var child_process = require('child_process');
-var stream = require('stream');
-var util = require('util');
-var Timer = process.binding('timer_wrap').Timer;
-var execSync = require('child_process').execSync;
-
-var testRoot = process.env.NODE_TEST_DIR ? fs.realpathSync(process.env.NODE_TEST_DIR) : __dirname;
-
-exports.fixturesDir = path.join(__dirname, 'fixtures');
-exports.tmpDirName = 'tmp';
-// PORT should match the definition in test/testpy/__init__.py.
-exports.PORT = +process.env.NODE_COMMON_PORT || 12346;
-exports.isWindows = process.platform === 'win32';
-exports.isWOW64 = exports.isWindows && process.env.PROCESSOR_ARCHITEW6432 !== undefined;
-exports.isAix = process.platform === 'aix';
-exports.isLinuxPPCBE = process.platform === 'linux' && process.arch === 'ppc64' && os.endianness() === 'BE';
-exports.isSunOS = process.platform === 'sunos';
-exports.isFreeBSD = process.platform === 'freebsd';
-exports.isLinux = process.platform === 'linux';
-exports.isOSX = process.platform === 'darwin';
-
-exports.enoughTestMem = os.totalmem() > 0x40000000; /* 1 Gb */
-
-var cpus = os.cpus();
-exports.enoughTestCpu = Array.isArray(cpus) && (cpus.length > 1 || cpus[0].speed > 999);
-
-exports.rootDir = exports.isWindows ? 'c:\\' : '/';
-exports.buildType = process.config.target_defaults.default_configuration;
-
-function rimrafSync(p) {
- var st = void 0;
- try {
- st = fs.lstatSync(p);
- } catch (e) {
- if (e.code === 'ENOENT') return;
- }
-
- try {
- if (st && st.isDirectory()) rmdirSync(p, null);else fs.unlinkSync(p);
- } catch (e) {
- if (e.code === 'ENOENT') return;
- if (e.code === 'EPERM') return rmdirSync(p, e);
- if (e.code !== 'EISDIR') throw e;
- rmdirSync(p, e);
- }
-}
-
-function rmdirSync(p, originalEr) {
- try {
- fs.rmdirSync(p);
- } catch (e) {
- if (e.code === 'ENOTDIR') throw originalEr;
- if (e.code === 'ENOTEMPTY' || e.code === 'EEXIST' || e.code === 'EPERM') {
- var enc = exports.isLinux ? 'buffer' : 'utf8';
- fs.readdirSync(p, enc).forEach(function (f) {
- if (f instanceof Buffer) {
- var buf = Buffer.concat([Buffer.from(p), Buffer.from(path.sep), f]);
- rimrafSync(buf);
- } else {
- rimrafSync(path.join(p, f));
- }
- });
- fs.rmdirSync(p);
- }
- }
-}
-
-exports.refreshTmpDir = function () {
- rimrafSync(exports.tmpDir);
- fs.mkdirSync(exports.tmpDir);
-};
-
-if (process.env.TEST_THREAD_ID) {
- exports.PORT += process.env.TEST_THREAD_ID * 100;
- exports.tmpDirName += '.' + process.env.TEST_THREAD_ID;
-}
-exports.tmpDir = path.join(testRoot, exports.tmpDirName);
-
-var opensslCli = null;
-var inFreeBSDJail = null;
-var localhostIPv4 = null;
-
-exports.localIPv6Hosts = ['localhost'];
-if (exports.isLinux) {
- exports.localIPv6Hosts = [
- // Debian/Ubuntu
- 'ip6-localhost', 'ip6-loopback',
-
- // SUSE
- 'ipv6-localhost', 'ipv6-loopback',
-
- // Typically universal
- 'localhost'];
-}
-
-Object.defineProperty(exports, 'inFreeBSDJail', {
- get: function () {
- if (inFreeBSDJail !== null) return inFreeBSDJail;
-
- if (exports.isFreeBSD && child_process.execSync('sysctl -n security.jail.jailed').toString() === '1\n') {
- inFreeBSDJail = true;
- } else {
- inFreeBSDJail = false;
- }
- return inFreeBSDJail;
- }
-});
-
-Object.defineProperty(exports, 'localhostIPv4', {
- get: function () {
- if (localhostIPv4 !== null) return localhostIPv4;
-
- if (exports.inFreeBSDJail) {
- // Jailed network interfaces are a bit special - since we need to jump
- // through loops, as well as this being an exception case, assume the
- // user will provide this instead.
- if (process.env.LOCALHOST) {
- localhostIPv4 = process.env.LOCALHOST;
- } else {
- console.error('Looks like we\'re in a FreeBSD Jail. ' + 'Please provide your default interface address ' + 'as LOCALHOST or expect some tests to fail.');
- }
- }
-
- if (localhostIPv4 === null) localhostIPv4 = '127.0.0.1';
-
- return localhostIPv4;
- }
-});
-
-// opensslCli defined lazily to reduce overhead of spawnSync
-Object.defineProperty(exports, 'opensslCli', { get: function () {
- if (opensslCli !== null) return opensslCli;
-
- if (process.config.variables.node_shared_openssl) {
- // use external command
- opensslCli = 'openssl';
- } else {
- // use command built from sources included in Node.js repository
- opensslCli = path.join(path.dirname(process.execPath), 'openssl-cli');
- }
-
- if (exports.isWindows) opensslCli += '.exe';
-
- var opensslCmd = child_process.spawnSync(opensslCli, ['version']);
- if (opensslCmd.status !== 0 || opensslCmd.error !== undefined) {
- // openssl command cannot be executed
- opensslCli = false;
- }
- return opensslCli;
- }, enumerable: true });
-
-Object.defineProperty(exports, 'hasCrypto', {
- get: function () {
- return process.versions.openssl ? true : false;
- }
-});
-
-Object.defineProperty(exports, 'hasFipsCrypto', {
- get: function () {
- return exports.hasCrypto && require('crypto').fips;
- }
-});
-
-if (exports.isWindows) {
- exports.PIPE = '\\\\.\\pipe\\libuv-test';
- if (process.env.TEST_THREAD_ID) {
- exports.PIPE += '.' + process.env.TEST_THREAD_ID;
- }
-} else {
- exports.PIPE = exports.tmpDir + '/test.sock';
-}
-
-var ifaces = os.networkInterfaces();
-exports.hasIPv6 = Object.keys(ifaces).some(function (name) {
- return (/lo/.test(name) && ifaces[name].some(function (info) {
- return info.family === 'IPv6';
- })
- );
-});
-
-/*
- * Check that when running a test with
- * `$node --abort-on-uncaught-exception $file child`
- * the process aborts.
- */
-exports.childShouldThrowAndAbort = function () {
- var testCmd = '';
- if (!exports.isWindows) {
- // Do not create core files, as it can take a lot of disk space on
- // continuous testing and developers' machines
- testCmd += 'ulimit -c 0 && ';
- }
- testCmd += process.argv[0] + ' --abort-on-uncaught-exception ';
- testCmd += process.argv[1] + ' child';
- var child = child_process.exec(testCmd);
- child.on('exit', function onExit(exitCode, signal) {
- var errMsg = 'Test should have aborted ' + ('but instead exited with exit code ' + exitCode) + (' and signal ' + signal);
- assert(exports.nodeProcessAborted(exitCode, signal), errMsg);
- });
-};
-
-exports.ddCommand = function (filename, kilobytes) {
- if (exports.isWindows) {
- var p = path.resolve(exports.fixturesDir, 'create-file.js');
- return '"' + process.argv[0] + '" "' + p + '" "' + filename + '" ' + kilobytes * 1024;
- } else {
- return 'dd if=/dev/zero of="' + filename + '" bs=1024 count=' + kilobytes;
- }
-};
-
-exports.spawnPwd = function (options) {
- var spawn = require('child_process').spawn;
-
- if (exports.isWindows) {
- return spawn('cmd.exe', ['/d', '/c', 'cd'], options);
- } else {
- return spawn('pwd', [], options);
- }
-};
-
-exports.spawnSyncPwd = function (options) {
- var spawnSync = require('child_process').spawnSync;
-
- if (exports.isWindows) {
- return spawnSync('cmd.exe', ['/d', '/c', 'cd'], options);
- } else {
- return spawnSync('pwd', [], options);
- }
-};
-
-exports.platformTimeout = function (ms) {
- if (process.config.target_defaults.default_configuration === 'Debug') ms = 2 * ms;
-
- if (global.__coverage__) ms = 4 * ms;
-
- if (exports.isAix) return 2 * ms; // default localhost speed is slower on AIX
-
- if (process.arch !== 'arm') return ms;
-
- var armv = process.config.variables.arm_version;
-
- if (armv === '6') return 7 * ms; // ARMv6
-
- if (armv === '7') return 2 * ms; // ARMv7
-
- return ms; // ARMv8+
-};
-
-var knownGlobals = [Buffer, clearImmediate, clearInterval, clearTimeout, console, constructor, // Enumerable in V8 3.21.
-global, process, setImmediate, setInterval, setTimeout];
-
-if (global.gc) {
- knownGlobals.push(global.gc);
-}
-
-if (global.DTRACE_HTTP_SERVER_RESPONSE) {
- knownGlobals.push(DTRACE_HTTP_SERVER_RESPONSE);
- knownGlobals.push(DTRACE_HTTP_SERVER_REQUEST);
- knownGlobals.push(DTRACE_HTTP_CLIENT_RESPONSE);
- knownGlobals.push(DTRACE_HTTP_CLIENT_REQUEST);
- knownGlobals.push(DTRACE_NET_STREAM_END);
- knownGlobals.push(DTRACE_NET_SERVER_CONNECTION);
-}
-
-if (global.COUNTER_NET_SERVER_CONNECTION) {
- knownGlobals.push(COUNTER_NET_SERVER_CONNECTION);
- knownGlobals.push(COUNTER_NET_SERVER_CONNECTION_CLOSE);
- knownGlobals.push(COUNTER_HTTP_SERVER_REQUEST);
- knownGlobals.push(COUNTER_HTTP_SERVER_RESPONSE);
- knownGlobals.push(COUNTER_HTTP_CLIENT_REQUEST);
- knownGlobals.push(COUNTER_HTTP_CLIENT_RESPONSE);
-}
-
-if (global.LTTNG_HTTP_SERVER_RESPONSE) {
- knownGlobals.push(LTTNG_HTTP_SERVER_RESPONSE);
- knownGlobals.push(LTTNG_HTTP_SERVER_REQUEST);
- knownGlobals.push(LTTNG_HTTP_CLIENT_RESPONSE);
- knownGlobals.push(LTTNG_HTTP_CLIENT_REQUEST);
- knownGlobals.push(LTTNG_NET_STREAM_END);
- knownGlobals.push(LTTNG_NET_SERVER_CONNECTION);
-}
-
-if (global.ArrayBuffer) {
- knownGlobals.push(ArrayBuffer);
- knownGlobals.push(Int8Array);
- knownGlobals.push(Uint8Array);
- knownGlobals.push(Uint8ClampedArray);
- knownGlobals.push(Int16Array);
- knownGlobals.push(Uint16Array);
- knownGlobals.push(Int32Array);
- knownGlobals.push(Uint32Array);
- knownGlobals.push(Float32Array);
- knownGlobals.push(Float64Array);
- knownGlobals.push(DataView);
-}
-
-// Harmony features.
-if (global.Proxy) {
- knownGlobals.push(Proxy);
-}
-
-if (global.Symbol) {
- knownGlobals.push(Symbol);
-}
-
-function allowGlobals() {
- for (var _len = arguments.length, whitelist = Array(_len), _key = 0; _key < _len; _key++) {
- whitelist[_key] = arguments[_key];
- }
-
- knownGlobals = knownGlobals.concat(whitelist);
-}
-exports.allowGlobals = allowGlobals;
-
-/**/
-if (typeof constructor == 'function') knownGlobals.push(constructor);
-if (typeof DTRACE_NET_SOCKET_READ == 'function') knownGlobals.push(DTRACE_NET_SOCKET_READ);
-if (typeof DTRACE_NET_SOCKET_WRITE == 'function') knownGlobals.push(DTRACE_NET_SOCKET_WRITE);
-if (global.__coverage__) knownGlobals.push(__coverage__);
-'core,__core-js_shared__,Promise,Map,Set,WeakMap,WeakSet,Reflect,System,asap,Observable,regeneratorRuntime,_babelPolyfill'.split(',').filter(function (item) {
- return typeof global[item] !== undefined;
-}).forEach(function (item) {
- knownGlobals.push(global[item]);
-}); /**/
-
-function leakedGlobals() {
- var leaked = [];
-
- for (var val in global) {
- if (!knownGlobals.includes(global[val])) leaked.push(val);
- }if (global.__coverage__) {
- return leaked.filter(function (varname) {
- return !/^(cov_|__cov)/.test(varname);
- });
- } else {
- return leaked;
- }
-}
-exports.leakedGlobals = leakedGlobals;
-
-// Turn this off if the test should not check for global leaks.
-exports.globalCheck = true;
-
-process.on('exit', function () {
- if (!exports.globalCheck) return;
- var leaked = leakedGlobals();
- if (leaked.length > 0) {
- fail('Unexpected global(s) found: ' + leaked.join(', '));
- }
-});
-
-var mustCallChecks = [];
-
-function runCallChecks(exitCode) {
- if (exitCode !== 0) return;
-
- var failed = mustCallChecks.filter(function (context) {
- return context.actual !== context.expected;
- });
-
- failed.forEach(function (context) {
- console.log('Mismatched %s function calls. Expected %d, actual %d.', context.name, context.expected, context.actual);
- console.log(context.stack.split('\n').slice(2).join('\n'));
- });
-
- if (failed.length) process.exit(1);
-}
-
-exports.mustCall = function (fn, expected) {
- if (expected === undefined) expected = 1;else if (typeof expected !== 'number') throw new TypeError('Invalid expected value: ' + expected);
-
- var context = {
- expected: expected,
- actual: 0,
- stack: new Error().stack,
- name: fn.name || ''
- };
-
- // add the exit listener only once to avoid listener leak warnings
- if (mustCallChecks.length === 0) process.on('exit', runCallChecks);
-
- mustCallChecks.push(context);
-
- return function () {
- context.actual++;
- return fn.apply(this, arguments);
- };
-};
-
-exports.hasMultiLocalhost = function hasMultiLocalhost() {
- var TCP = process.binding('tcp_wrap').TCP;
- var t = new TCP();
- var ret = t.bind('127.0.0.2', exports.PORT);
- t.close();
- return ret === 0;
-};
-
-exports.fileExists = function (pathname) {
- try {
- fs.accessSync(pathname);
- return true;
- } catch (err) {
- return false;
- }
-};
-
-exports.canCreateSymLink = function () {
- // On Windows, creating symlinks requires admin privileges.
- // We'll only try to run symlink test if we have enough privileges.
- // On other platforms, creating symlinks shouldn't need admin privileges
- if (exports.isWindows) {
- // whoami.exe needs to be the one from System32
- // If unix tools are in the path, they can shadow the one we want,
- // so use the full path while executing whoami
- var whoamiPath = path.join(process.env['SystemRoot'], 'System32', 'whoami.exe');
-
- var err = false;
- var output = '';
-
- try {
- output = execSync(whoamiPath + ' /priv', { timout: 1000 });
- } catch (e) {
- err = true;
- } finally {
- if (err || !output.includes('SeCreateSymbolicLinkPrivilege')) {
- return false;
- }
- }
- }
-
- return true;
-};
-
-function fail(msg) {
- assert.fail(null, null, msg);
-}
-exports.fail = fail;
-
-exports.mustNotCall = function (msg) {
- return function mustNotCall() {
- fail(msg || 'function should not have been called');
- };
-};
-
-exports.skip = function (msg) {
- console.log('1..0 # Skipped: ' + msg);
-};
-
-// A stream to push an array into a REPL
-function ArrayStream() {
- this.run = function (data) {
- var _this = this;
-
- data.forEach(function (line) {
- _this.emit('data', line + '\n');
- });
- };
-}
-
-util.inherits(ArrayStream, stream.Stream);
-exports.ArrayStream = ArrayStream;
-ArrayStream.prototype.readable = true;
-ArrayStream.prototype.writable = true;
-ArrayStream.prototype.pause = function () {};
-ArrayStream.prototype.resume = function () {};
-ArrayStream.prototype.write = function () {};
-
-// Returns true if the exit code "exitCode" and/or signal name "signal"
-// represent the exit code and/or signal name of a node process that aborted,
-// false otherwise.
-exports.nodeProcessAborted = function nodeProcessAborted(exitCode, signal) {
- // Depending on the compiler used, node will exit with either
- // exit code 132 (SIGILL), 133 (SIGTRAP) or 134 (SIGABRT).
- var expectedExitCodes = [132, 133, 134];
-
- // On platforms using KSH as the default shell (like SmartOS),
- // when a process aborts, KSH exits with an exit code that is
- // greater than 256, and thus the exit code emitted with the 'exit'
- // event is null and the signal is set to either SIGILL, SIGTRAP,
- // or SIGABRT (depending on the compiler).
- var expectedSignals = ['SIGILL', 'SIGTRAP', 'SIGABRT'];
-
- // On Windows, v8's base::OS::Abort triggers an access violation,
- // which corresponds to exit code 3221225477 (0xC0000005)
- if (exports.isWindows) expectedExitCodes = [3221225477];
-
- // When using --abort-on-uncaught-exception, V8 will use
- // base::OS::Abort to terminate the process.
- // Depending on the compiler used, the shell or other aspects of
- // the platform used to build the node binary, this will actually
- // make V8 exit by aborting or by raising a signal. In any case,
- // one of them (exit code or signal) needs to be set to one of
- // the expected exit codes or signals.
- if (signal !== null) {
- return expectedSignals.includes(signal);
- } else {
- return expectedExitCodes.includes(exitCode);
- }
-};
-
-exports.busyLoop = function busyLoop(time) {
- var startTime = Timer.now();
- var stopTime = startTime + time;
- while (Timer.now() < stopTime) {}
-};
-
-exports.isAlive = function isAlive(pid) {
- try {
- process.kill(pid, 'SIGCONT');
- return true;
- } catch (e) {
- return false;
- }
-};
-
-exports.expectWarning = function (name, expected) {
- if (typeof expected === 'string') expected = [expected];
- process.on('warning', exports.mustCall(function (warning) {
- assert.strictEqual(warning.name, name);
- assert.ok(expected.includes(warning.message), 'unexpected error message: "' + warning.message + '"');
- // Remove a warning message after it is seen so that we guarantee that we
- // get each message only once.
- expected.splice(expected.indexOf(warning.message), 1);
- }, expected.length));
-};
-
-Object.defineProperty(exports, 'hasIntl', {
- get: function () {
- return process.binding('config').hasIntl;
- }
-});
-
-// https://github.com/w3c/testharness.js/blob/master/testharness.js
-exports.WPT = {
- test: function (fn, desc) {
- try {
- fn();
- } catch (err) {
- if (err instanceof Error) err.message = 'In ' + desc + ':\n ' + err.message;
- throw err;
- }
- },
- assert_equals: assert.strictEqual,
- assert_true: function (value, message) {
- return assert.strictEqual(value, true, message);
- },
- assert_false: function (value, message) {
- return assert.strictEqual(value, false, message);
- },
- assert_throws: function (code, func, desc) {
- assert.throws(func, function (err) {
- return typeof err === 'object' && 'name' in err && err.name === code.name;
- }, desc);
- },
- assert_array_equals: assert.deepStrictEqual,
- assert_unreached: function (desc) {
- assert.fail(undefined, undefined, 'Reached unreachable code: ' + desc);
- }
-};
-
-// Useful for testing expected internal/error objects
-exports.expectsError = function expectsError(_ref) {
- var code = _ref.code,
- type = _ref.type,
- message = _ref.message;
-
- return function (error) {
- assert.strictEqual(error.code, code);
- if (type !== undefined) assert(error instanceof type, error + ' is not the expected type ' + type);
- if (message instanceof RegExp) {
- assert(message.test(error.message), error.message + ' does not match ' + message);
- } else if (typeof message === 'string') {
- assert.strictEqual(error.message, message);
- }
- return true;
- };
-};
\ No newline at end of file
diff --git a/test/common/README.md b/test/common/README.md
new file mode 100644
index 0000000..0e25d98
--- /dev/null
+++ b/test/common/README.md
@@ -0,0 +1,541 @@
+/**/
+ require('babel-polyfill');
+ var util = require('util');
+ for (var i in util) exports[i] = util[i];
+ /**//**/
+if (!global.setImmediate) {
+ global.setImmediate = function setImmediate(fn) {
+ return setTimeout(fn.bind.apply(fn, arguments), 4);
+ };
+}
+if (!global.clearImmediate) {
+ global.clearImmediate = function clearImmediate(i) {
+ return clearTimeout(i);
+ };
+}
+/**/
+# Node.js Core Test Common Modules
+
+This directory contains modules used to test the Node.js implementation.
+
+## Table of Contents
+
+* [Benchmark module](#benchmark-module)
+* [Common module API](#common-module-api)
+* [Countdown module](#countdown-module)
+* [DNS module](#dns-module)
+* [Duplex pair helper](#duplex-pair-helper)
+* [Fixtures module](#fixtures-module)
+* [WPT module](#wpt-module)
+
+## Benchmark Module
+
+The `benchmark` module is used by tests to run benchmarks.
+
+### runBenchmark(name, args, env)
+
+* `name` [<String>] Name of benchmark suite to be run.
+* `args` [<Array>] Array of environment variable key/value pairs (ex:
+ `n=1`) to be applied via `--set`.
+* `env` [<Object>] Environment variables to be applied during the run.
+
+## Common Module API
+
+The `common` module is used by tests for consistency across repeated
+tasks.
+
+### allowGlobals(...whitelist)
+* `whitelist` [<Array>] Array of Globals
+* return [<Array>]
+
+Takes `whitelist` and concats that with predefined `knownGlobals`.
+
+### arrayStream
+A stream to push an array into a REPL
+
+### busyLoop(time)
+* `time` [<Number>]
+
+Blocks for `time` amount of time.
+
+### canCreateSymLink()
+* return [<Boolean>]
+
+Checks whether the current running process can create symlinks. On Windows, this
+returns `false` if the process running doesn't have privileges to create
+symlinks
+([SeCreateSymbolicLinkPrivilege](https://msdn.microsoft.com/en-us/library/windows/desktop/bb530716(v=vs.85).aspx)).
+On non-Windows platforms, this always returns `true`.
+
+### crashOnUnhandledRejection()
+
+Installs a `process.on('unhandledRejection')` handler that crashes the process
+after a tick. This is useful for tests that use Promises and need to make sure
+no unexpected rejections occur, because currently they result in silent
+failures.
+
+### ddCommand(filename, kilobytes)
+* return [<Object>]
+
+Platform normalizes the `dd` command
+
+### enoughTestMem
+* [<Boolean>]
+
+Indicates if there is more than 1gb of total memory.
+
+### expectsError([fn, ]settings[, exact])
+* `fn` [<Function>] a function that should throw.
+* `settings` [<Object>]
+ that must contain the `code` property plus any of the other following
+ properties (some properties only apply for `AssertionError`):
+ * `code` [<String>]
+ expected error must have this value for its `code` property.
+ * `type` [<Function>]
+ expected error must be an instance of `type` and must be an Error subclass.
+ * `message` [<String>] or [<RegExp>]
+ if a string is provided for `message`, expected error must have it for its
+ `message` property; if a regular expression is provided for `message`, the
+ regular expression must match the `message` property of the expected error.
+ * `name` [<String>]
+ expected error must have this value for its `name` property.
+ * `generatedMessage` [<String>]
+ (`AssertionError` only) expected error must have this value for its
+ `generatedMessage` property.
+ * `actual` <any>
+ (`AssertionError` only) expected error must have this value for its
+ `actual` property.
+ * `expected` <any>
+ (`AssertionError` only) expected error must have this value for its
+ `expected` property.
+ * `operator` <any>
+ (`AssertionError` only) expected error must have this value for its
+ `operator` property.
+* `exact` [<Number>] default = 1
+* return [<Function>]
+
+ If `fn` is provided, it will be passed to `assert.throws` as first argument
+ and `undefined` will be returned.
+ Otherwise a function suitable as callback or for use as a validation function
+ passed as the second argument to `assert.throws()` will be returned. If the
+ returned function has not been called exactly `exact` number of times when the
+ test is complete, then the test will fail.
+
+### expectWarning(name, expected)
+* `name` [<String>]
+* `expected` [<String>] | [<Array>]
+
+Tests whether `name` and `expected` are part of a raised warning.
+
+### fileExists(pathname)
+* pathname [<String>]
+* return [<Boolean>]
+
+Checks if `pathname` exists
+
+### fires(promise, [error], [timeoutMs])
+* promise [<Promise]
+* error [<String] default = 'timeout'
+* timeoutMs [<Number] default = 100
+
+Returns a new promise that will propagate `promise` resolution or rejection if
+that happens within the `timeoutMs` timespan, or rejects with `error` as
+a reason otherwise.
+
+### getArrayBufferViews(buf)
+* `buf` [<Buffer>]
+* return [<ArrayBufferView[]>]
+
+Returns an instance of all possible `ArrayBufferView`s of the provided Buffer.
+
+### getCallSite(func)
+* `func` [<Function>]
+* return [<String>]
+
+Returns the file name and line number for the provided Function.
+
+### globalCheck
+* [<Boolean>]
+
+Set to `false` if the test should not check for global leaks.
+
+### hasCrypto
+* [<Boolean>]
+
+Indicates whether OpenSSL is available.
+
+### hasFipsCrypto
+* [<Boolean>]
+
+Indicates `hasCrypto` and `crypto` with fips.
+
+### hasIntl
+* [<Boolean>]
+
+Indicates if [internationalization] is supported.
+
+### hasSmallICU
+* [<Boolean>]
+
+Indicates `hasIntl` and `small-icu` are supported.
+
+### hasIPv6
+* [<Boolean>]
+
+Indicates whether `IPv6` is supported on this platform.
+
+### hasMultiLocalhost
+* [<Boolean>]
+
+Indicates if there are multiple localhosts available.
+
+### hijackStderr(listener)
+* `listener` [<Function>]: a listener with a single parameter
+ called `data`.
+
+Eavesdrop to `process.stderr.write` calls. Once `process.stderr.write` is
+called, `listener` will also be called and the `data` of `write` function will
+be passed to `listener`. What's more, `process.stderr.writeTimes` is a count of
+the number of calls.
+
+### hijackStdout(listener)
+* `listener` [<Function>]: a listener with a single parameter
+ called `data`.
+
+Eavesdrop to `process.stdout.write` calls. Once `process.stdout.write` is
+called, `listener` will also be called and the `data` of `write` function will
+be passed to `listener`. What's more, `process.stdout.writeTimes` is a count of
+the number of calls.
+
+### inFreeBSDJail
+* [<Boolean>]
+
+Checks whether free BSD Jail is true or false.
+
+### isAIX
+* [<Boolean>]
+
+Platform check for Advanced Interactive eXecutive (AIX).
+
+### isAlive(pid)
+* `pid` [<Number>]
+* return [<Boolean>]
+
+Attempts to 'kill' `pid`
+
+### isFreeBSD
+* [<Boolean>]
+
+Platform check for Free BSD.
+
+### isLinux
+* [<Boolean>]
+
+Platform check for Linux.
+
+### isLinuxPPCBE
+* [<Boolean>]
+
+Platform check for Linux on PowerPC.
+
+### isOSX
+* [<Boolean>]
+
+Platform check for macOS.
+
+### isSunOS
+* [<Boolean>]
+
+Platform check for SunOS.
+
+### isWindows
+* [<Boolean>]
+
+Platform check for Windows.
+
+### isWOW64
+* [<Boolean>]
+
+Platform check for Windows 32-bit on Windows 64-bit.
+
+### leakedGlobals()
+* return [<Array>]
+
+Indicates whether any globals are not on the `knownGlobals` list.
+
+### localhostIPv4
+* [<String>]
+
+IP of `localhost`.
+
+### localIPv6Hosts
+* [<Array>]
+
+Array of IPV6 representations for `localhost`.
+
+### mustCall([fn][, exact])
+* `fn` [<Function>] default = () => {}
+* `exact` [<Number>] default = 1
+* return [<Function>]
+
+Returns a function that calls `fn`. If the returned function has not been called
+exactly `exact` number of times when the test is complete, then the test will
+fail.
+
+If `fn` is not provided, an empty function will be used.
+
+### mustCallAtLeast([fn][, minimum])
+* `fn` [<Function>] default = () => {}
+* `minimum` [<Number>] default = 1
+* return [<Function>]
+
+Returns a function that calls `fn`. If the returned function has not been called
+at least `minimum` number of times when the test is complete, then the test will
+fail.
+
+If `fn` is not provided, an empty function will be used.
+
+### mustNotCall([msg])
+* `msg` [<String>] default = 'function should not have been called'
+* return [<Function>]
+
+Returns a function that triggers an `AssertionError` if it is invoked. `msg` is
+used as the error message for the `AssertionError`.
+
+### nodeProcessAborted(exitCode, signal)
+* `exitCode` [<Number>]
+* `signal` [<String>]
+* return [<Boolean>]
+
+Returns `true` if the exit code `exitCode` and/or signal name `signal` represent
+the exit code and/or signal name of a node process that aborted, `false`
+otherwise.
+
+### opensslCli
+* [<Boolean>]
+
+Indicates whether 'opensslCli' is supported.
+
+### platformTimeout(ms)
+* `ms` [<Number>]
+* return [<Number>]
+
+Platform normalizes timeout.
+
+### PIPE
+* [<String>]
+
+Path to the test socket.
+
+### PORT
+* [<Number>]
+
+A port number for tests to use if one is needed.
+
+### printSkipMessage(msg)
+* `msg` [<String>]
+
+Logs '1..0 # Skipped: ' + `msg`
+
+### refreshTmpDir()
+* return [<String>]
+
+Deletes the testing 'tmp' directory and recreates it.
+
+### restoreStderr()
+
+Restore the original `process.stderr.write`. Used to restore `stderr` to its
+original state after calling [`common.hijackStdErr()`][].
+
+### restoreStdout()
+
+Restore the original `process.stdout.write`. Used to restore `stdout` to its
+original state after calling [`common.hijackStdOut()`][].
+
+### rootDir
+* [<String>]
+
+Path to the 'root' directory. either `/` or `c:\\` (windows)
+
+### projectDir
+* [<String>]
+
+Path to the project directory.
+
+### skip(msg)
+* `msg` [<String>]
+
+Logs '1..0 # Skipped: ' + `msg` and exits with exit code `0`.
+
+### skipIfInspectorDisabled()
+
+Skip the rest of the tests in the current file when the Inspector
+was disabled at compile time.
+
+### skipIf32Bits()
+
+Skip the rest of the tests in the current file when the Node.js executable
+was compiled with a pointer size smaller than 64 bits.
+
+### spawnPwd(options)
+* `options` [<Object>]
+* return [<Object>]
+
+Platform normalizes the `pwd` command.
+
+### spawnSyncPwd(options)
+* `options` [<Object>]
+* return [<Object>]
+
+Synchronous version of `spawnPwd`.
+
+### tmpDir
+* [<String>]
+
+The realpath of the 'tmp' directory.
+
+## Countdown Module
+
+The `Countdown` module provides a simple countdown mechanism for tests that
+require a particular action to be taken after a given number of completed
+tasks (for instance, shutting down an HTTP server after a specific number of
+requests).
+
+
+```js
+const Countdown = require('../common/countdown');
+
+function doSomething() {
+ console.log('.');
+}
+
+const countdown = new Countdown(2, doSomething);
+countdown.dec();
+countdown.dec();
+```
+
+### new Countdown(limit, callback)
+
+* `limit` {number}
+* `callback` {function}
+
+Creates a new `Countdown` instance.
+
+### Countdown.prototype.dec()
+
+Decrements the `Countdown` counter.
+
+### Countdown.prototype.remaining
+
+Specifies the remaining number of times `Countdown.prototype.dec()` must be
+called before the callback is invoked.
+
+## DNS Module
+
+The `DNS` module provides a naïve DNS parser/serializer.
+
+### readDomainFromPacket(buffer, offset)
+
+* `buffer` [<Buffer>]
+* `offset` [<Number>]
+* return [<Object>]
+
+Reads the domain string from a packet and returns an object containing the
+number of bytes read and the domain.
+
+### parseDNSPacket(buffer)
+
+* `buffer` [<Buffer>]
+* return [<Object>]
+
+Parses a DNS packet. Returns an object with the values of the various flags of
+the packet depending on the type of packet.
+
+### writeIPv6(ip)
+
+* `ip` [<String>]
+* return [<Buffer>]
+
+Reads an IPv6 String and returns a Buffer containing the parts.
+
+### writeDomainName(domain)
+
+* `domain` [<String>]
+* return [<Buffer>]
+
+Reads a Domain String and returns a Buffer containing the domain.
+
+### writeDNSPacket(parsed)
+
+* `parsed` [<Object>]
+* return [<Buffer>]
+
+Takes in a parsed Object and writes its fields to a DNS packet as a Buffer
+object.
+
+## Duplex pair helper
+
+The `common/duplexpair` module exports a single function `makeDuplexPair`,
+which returns an object `{ clientSide, serverSide }` where each side is a
+`Duplex` stream connected to the other side.
+
+There is no difference between client or server side beyond their names.
+
+## Fixtures Module
+
+The `common/fixtures` module provides convenience methods for working with
+files in the `test/fixtures` directory.
+
+### fixtures.fixturesDir
+
+* [<String>]
+
+The absolute path to the `test/fixtures/` directory.
+
+### fixtures.path(...args)
+
+* `...args` [<String>]
+
+Returns the result of `path.join(fixtures.fixturesDir, ...args)`.
+
+### fixtures.readSync(args[, enc])
+
+* `args` [<String>] | [<Array>]
+
+Returns the result of
+`fs.readFileSync(path.join(fixtures.fixturesDir, ...args), 'enc')`.
+
+### fixtures.readKey(arg[, enc])
+
+* `arg` [<String>]
+
+Returns the result of
+`fs.readFileSync(path.join(fixtures.fixturesDir, 'keys', arg), 'enc')`.
+
+## WPT Module
+
+The wpt.js module is a port of parts of
+[W3C testharness.js](https://github.com/w3c/testharness.js) for testing the
+Node.js
+[WHATWG URL API](https://nodejs.org/api/url.html#url_the_whatwg_url_api)
+implementation with tests from
+[W3C Web Platform Tests](https://github.com/w3c/web-platform-tests).
+
+[<Array>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
+[<ArrayBufferView[]>]: https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView
+[<Boolean>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type
+[<Buffer>]: https://nodejs.org/api/buffer.html#buffer_class_buffer
+[<Function>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function
+[<Number>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type
+[<Object>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
+[<RegExp>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
+[<String>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type
+[`common.hijackStdErr()`]: #hijackstderrlistener
+[`common.hijackStdOut()`]: #hijackstdoutlistener
+[internationalization]: https://github.com/nodejs/node/wiki/Intl
+
+function forEach (xs, f) {
+ for (var i = 0, l = xs.length; i < l; i++) {
+ f(xs[i], i);
+ }
+}
diff --git a/test/common/benchmark.js b/test/common/benchmark.js
new file mode 100644
index 0000000..555dc62
--- /dev/null
+++ b/test/common/benchmark.js
@@ -0,0 +1,62 @@
+/**/
+require('babel-polyfill');
+var util = require('util');
+for (var i in util) {
+ exports[i] = util[i];
+} /**/ /**/
+if (!global.setImmediate) {
+ global.setImmediate = function setImmediate(fn) {
+ return setTimeout(fn.bind.apply(fn, arguments), 4);
+ };
+}
+if (!global.clearImmediate) {
+ global.clearImmediate = function clearImmediate(i) {
+ return clearTimeout(i);
+ };
+}
+/**/
+/* eslint-disable required-modules */
+
+'use strict';
+
+/**/
+var objectKeys = objectKeys || function (obj) {
+ var keys = [];
+ for (var key in obj) {
+ keys.push(key);
+ }return keys;
+};
+/**/
+
+var assert = require('assert');
+var fork = require('child_process').fork;
+var path = require('path');
+
+var runjs = path.join(__dirname, '..', '..', 'benchmark', 'run.js');
+
+function runBenchmark(name, args, env) {
+ var argv = [];
+
+ for (var _i = 0; _i < args.length; _i++) {
+ argv.push('--set');
+ argv.push(args[_i]);
+ }
+
+ argv.push(name);
+
+ var mergedEnv = Object.assign({}, process.env, env);
+
+ var child = fork(runjs, argv, { env: mergedEnv });
+ child.on('exit', function (code, signal) {
+ assert.strictEqual(code, 0);
+ assert.strictEqual(signal, null);
+ });
+}
+
+module.exports = runBenchmark;
+
+function forEach(xs, f) {
+ for (var i = 0, l = xs.length; i < l; i++) {
+ f(xs[i], i);
+ }
+}
\ No newline at end of file
diff --git a/test/common/countdown.js b/test/common/countdown.js
new file mode 100644
index 0000000..411fb69
--- /dev/null
+++ b/test/common/countdown.js
@@ -0,0 +1,70 @@
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**/
+require('babel-polyfill');
+var util = require('util');
+for (var i in util) {
+ exports[i] = util[i];
+} /**/ /**/
+if (!global.setImmediate) {
+ global.setImmediate = function setImmediate(fn) {
+ return setTimeout(fn.bind.apply(fn, arguments), 4);
+ };
+}
+if (!global.clearImmediate) {
+ global.clearImmediate = function clearImmediate(i) {
+ return clearTimeout(i);
+ };
+}
+/**/
+/* eslint-disable required-modules */
+'use strict';
+
+/**/
+var objectKeys = objectKeys || function (obj) {
+ var keys = [];
+ for (var key in obj) {
+ keys.push(key);
+ }return keys;
+};
+/**/
+
+var assert = require('assert');
+var kLimit = Symbol('limit');
+var kCallback = Symbol('callback');
+
+var Countdown = function () {
+ function Countdown(limit, cb) {
+ _classCallCheck(this, Countdown);
+
+ assert.strictEqual(typeof limit, 'number');
+ assert.strictEqual(typeof cb, 'function');
+ this[kLimit] = limit;
+ this[kCallback] = cb;
+ }
+
+ Countdown.prototype.dec = function dec() {
+ assert(this[kLimit] > 0, 'Countdown expired');
+ if (--this[kLimit] === 0) this[kCallback]();
+ return this[kLimit];
+ };
+
+ _createClass(Countdown, [{
+ key: 'remaining',
+ get: function () {
+ return this[kLimit];
+ }
+ }]);
+
+ return Countdown;
+}();
+
+module.exports = Countdown;
+
+function forEach(xs, f) {
+ for (var i = 0, l = xs.length; i < l; i++) {
+ f(xs[i], i);
+ }
+}
\ No newline at end of file
diff --git a/test/common/dns.js b/test/common/dns.js
new file mode 100644
index 0000000..388c8df
--- /dev/null
+++ b/test/common/dns.js
@@ -0,0 +1,418 @@
+var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
+
+/**/
+require('babel-polyfill');
+var util = require('util');
+for (var i in util) {
+ exports[i] = util[i];
+} /**/ /**/
+if (!global.setImmediate) {
+ global.setImmediate = function setImmediate(fn) {
+ return setTimeout(fn.bind.apply(fn, arguments), 4);
+ };
+}
+if (!global.clearImmediate) {
+ global.clearImmediate = function clearImmediate(i) {
+ return clearTimeout(i);
+ };
+}
+/**/
+/* eslint-disable required-modules */
+'use strict';
+
+/**/
+var objectKeys = objectKeys || function (obj) {
+ var keys = [];
+ for (var key in obj) {
+ keys.push(key);
+ }return keys;
+};
+/**/
+
+// Naïve DNS parser/serializer.
+
+var assert = require('assert');
+var os = require('os');
+
+var types = {
+ A: 1,
+ AAAA: 28,
+ NS: 2,
+ CNAME: 5,
+ SOA: 6,
+ PTR: 12,
+ MX: 15,
+ TXT: 16,
+ ANY: 255
+};
+
+var classes = {
+ IN: 1
+};
+
+function readDomainFromPacket(buffer, offset) {
+ assert.ok(offset < buffer.length);
+ var length = buffer[offset];
+ if (length === 0) {
+ return { nread: 1, domain: '' };
+ } else if ((length & 0xC0) === 0) {
+ offset += 1;
+ var chunk = buffer.toString('ascii', offset, offset + length);
+ // Read the rest of the domain.
+
+ var _readDomainFromPacket = readDomainFromPacket(buffer, offset + length),
+ nread = _readDomainFromPacket.nread,
+ domain = _readDomainFromPacket.domain;
+
+ return {
+ nread: 1 + length + nread,
+ domain: domain ? chunk + '.' + domain : chunk
+ };
+ } else {
+ // Pointer to another part of the packet.
+ assert.strictEqual(length & 0xC0, 0xC0);
+ // eslint-disable-next-line
+ var pointeeOffset = buffer.readUInt16BE(offset) & ~0xC000;
+ return {
+ nread: 2,
+ domain: readDomainFromPacket(buffer, pointeeOffset)
+ };
+ }
+}
+
+function parseDNSPacket(buffer) {
+ assert.ok(buffer.length > 12);
+
+ var parsed = {
+ id: buffer.readUInt16BE(0),
+ flags: buffer.readUInt16BE(2)
+ };
+
+ var counts = [['questions', buffer.readUInt16BE(4)], ['answers', buffer.readUInt16BE(6)], ['authorityAnswers', buffer.readUInt16BE(8)], ['additionalRecords', buffer.readUInt16BE(10)]];
+
+ var offset = 12;
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = counts[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ var _step$value = _slicedToArray(_step.value, 2),
+ sectionName = _step$value[0],
+ count = _step$value[1];
+
+ parsed[sectionName] = [];
+ for (var _i = 0; _i < count; ++_i) {
+ var _readDomainFromPacket2 = readDomainFromPacket(buffer, offset),
+ nread = _readDomainFromPacket2.nread,
+ domain = _readDomainFromPacket2.domain;
+
+ offset += nread;
+
+ var type = buffer.readUInt16BE(offset);
+
+ var rr = {
+ domain: domain,
+ cls: buffer.readUInt16BE(offset + 2)
+ };
+ offset += 4;
+
+ for (var name in types) {
+ if (types[name] === type) rr.type = name;
+ }
+
+ if (sectionName !== 'questions') {
+ rr.ttl = buffer.readInt32BE(offset);
+ var dataLength = buffer.readUInt16BE(offset);
+ offset += 6;
+
+ switch (type) {
+ case types.A:
+ assert.strictEqual(dataLength, 4);
+ rr.address = buffer[offset + 0] + '.' + buffer[offset + 1] + '.' + (buffer[offset + 2] + '.' + buffer[offset + 3]);
+ break;
+ case types.AAAA:
+ assert.strictEqual(dataLength, 16);
+ rr.address = buffer.toString('hex', offset, offset + 16).replace(/(.{4}(?!$))/g, '$1:');
+ break;
+ case types.TXT:
+ {
+ var position = offset;
+ rr.entries = [];
+ while (position < offset + dataLength) {
+ var txtLength = buffer[offset];
+ rr.entries.push(buffer.toString('utf8', position + 1, position + 1 + txtLength));
+ position += 1 + txtLength;
+ }
+ assert.strictEqual(position, offset + dataLength);
+ break;
+ }
+ case types.MX:
+ {
+ rr.priority = buffer.readInt16BE(buffer, offset);
+ offset += 2;
+
+ var _readDomainFromPacket3 = readDomainFromPacket(buffer, offset),
+ _nread = _readDomainFromPacket3.nread,
+ _domain = _readDomainFromPacket3.domain;
+
+ rr.exchange = _domain;
+ assert.strictEqual(_nread, dataLength);
+ break;
+ }
+ case types.NS:
+ case types.CNAME:
+ case types.PTR:
+ {
+ var _readDomainFromPacket4 = readDomainFromPacket(buffer, offset),
+ _nread2 = _readDomainFromPacket4.nread,
+ _domain2 = _readDomainFromPacket4.domain;
+
+ rr.value = _domain2;
+ assert.strictEqual(_nread2, dataLength);
+ break;
+ }
+ case types.SOA:
+ {
+ var mname = readDomainFromPacket(buffer, offset);
+ var rname = readDomainFromPacket(buffer, offset + mname.nread);
+ rr.nsname = mname.domain;
+ rr.hostmaster = rname.domain;
+ var trailerOffset = offset + mname.nread + rname.nread;
+ rr.serial = buffer.readUInt32BE(trailerOffset);
+ rr.refresh = buffer.readUInt32BE(trailerOffset + 4);
+ rr.retry = buffer.readUInt32BE(trailerOffset + 8);
+ rr.expire = buffer.readUInt32BE(trailerOffset + 12);
+ rr.minttl = buffer.readUInt32BE(trailerOffset + 16);
+
+ assert.strictEqual(trailerOffset + 20, dataLength);
+ break;
+ }
+ default:
+ throw new Error('Unknown RR type ' + rr.type);
+ }
+ offset += dataLength;
+ }
+
+ parsed[sectionName].push(rr);
+
+ assert.ok(offset <= buffer.length);
+ }
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+
+ assert.strictEqual(offset, buffer.length);
+ return parsed;
+}
+
+function writeIPv6(ip) {
+ var parts = ip.replace(/^:|:$/g, '').split(':');
+ var buf = Buffer.alloc(16);
+
+ var offset = 0;
+ var _iteratorNormalCompletion2 = true;
+ var _didIteratorError2 = false;
+ var _iteratorError2 = undefined;
+
+ try {
+ for (var _iterator2 = parts[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+ var part = _step2.value;
+
+ if (part === '') {
+ offset += 16 - 2 * (parts.length - 1);
+ } else {
+ buf.writeUInt16BE(parseInt(part, 16), offset);
+ offset += 2;
+ }
+ }
+ } catch (err) {
+ _didIteratorError2 = true;
+ _iteratorError2 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion2 && _iterator2.return) {
+ _iterator2.return();
+ }
+ } finally {
+ if (_didIteratorError2) {
+ throw _iteratorError2;
+ }
+ }
+ }
+
+ return buf;
+}
+
+function writeDomainName(domain) {
+ return Buffer.concat(domain.split('.').map(function (label) {
+ assert(label.length < 64);
+ return Buffer.concat([Buffer.from([label.length]), Buffer.from(label, 'ascii')]);
+ }).concat([Buffer.alloc(1)]));
+}
+
+function writeDNSPacket(parsed) {
+ var buffers = [];
+ var kStandardResponseFlags = 0x8180;
+
+ buffers.push(new Uint16Array([parsed.id, parsed.flags === undefined ? kStandardResponseFlags : parsed.flags, parsed.questions && parsed.questions.length, parsed.answers && parsed.answers.length, parsed.authorityAnswers && parsed.authorityAnswers.length, parsed.additionalRecords && parsed.additionalRecords.length]));
+
+ var _iteratorNormalCompletion3 = true;
+ var _didIteratorError3 = false;
+ var _iteratorError3 = undefined;
+
+ try {
+ for (var _iterator3 = parsed.questions[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
+ var q = _step3.value;
+
+ assert(types[q.type]);
+ buffers.push(writeDomainName(q.domain));
+ buffers.push(new Uint16Array([types[q.type], q.cls === undefined ? classes.IN : q.cls]));
+ }
+ } catch (err) {
+ _didIteratorError3 = true;
+ _iteratorError3 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion3 && _iterator3.return) {
+ _iterator3.return();
+ }
+ } finally {
+ if (_didIteratorError3) {
+ throw _iteratorError3;
+ }
+ }
+ }
+
+ var _iteratorNormalCompletion4 = true;
+ var _didIteratorError4 = false;
+ var _iteratorError4 = undefined;
+
+ try {
+ for (var _iterator4 = [].concat(parsed.answers, parsed.authorityAnswers, parsed.additionalRecords)[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
+ var rr = _step4.value;
+
+ if (!rr) continue;
+
+ assert(types[rr.type]);
+ buffers.push(writeDomainName(rr.domain));
+ buffers.push(new Uint16Array([types[rr.type], rr.cls === undefined ? classes.IN : rr.cls]));
+ buffers.push(new Int32Array([rr.ttl]));
+
+ var rdLengthBuf = new Uint16Array(1);
+ buffers.push(rdLengthBuf);
+
+ switch (rr.type) {
+ case 'A':
+ rdLengthBuf[0] = 4;
+ buffers.push(new Uint8Array(rr.address.split('.')));
+ break;
+ case 'AAAA':
+ rdLengthBuf[0] = 16;
+ buffers.push(writeIPv6(rr.address));
+ break;
+ case 'TXT':
+ var total = rr.entries.map(function (s) {
+ return s.length;
+ }).reduce(function (a, b) {
+ return a + b;
+ });
+ // Total length of all strings + 1 byte each for their lengths.
+ rdLengthBuf[0] = rr.entries.length + total;
+ var _iteratorNormalCompletion5 = true;
+ var _didIteratorError5 = false;
+ var _iteratorError5 = undefined;
+
+ try {
+ for (var _iterator5 = rr.entries[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
+ var txt = _step5.value;
+
+ buffers.push(new Uint8Array([Buffer.byteLength(txt)]));
+ buffers.push(Buffer.from(txt));
+ }
+ } catch (err) {
+ _didIteratorError5 = true;
+ _iteratorError5 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion5 && _iterator5.return) {
+ _iterator5.return();
+ }
+ } finally {
+ if (_didIteratorError5) {
+ throw _iteratorError5;
+ }
+ }
+ }
+
+ break;
+ case 'MX':
+ rdLengthBuf[0] = 2;
+ buffers.push(new Uint16Array([rr.priority]));
+ // fall through
+ case 'NS':
+ case 'CNAME':
+ case 'PTR':
+ {
+ var domain = writeDomainName(rr.exchange || rr.value);
+ rdLengthBuf[0] += domain.length;
+ buffers.push(domain);
+ break;
+ }
+ case 'SOA':
+ {
+ var mname = writeDomainName(rr.nsname);
+ var rname = writeDomainName(rr.hostmaster);
+ rdLengthBuf[0] = mname.length + rname.length + 20;
+ buffers.push(mname, rname);
+ buffers.push(new Uint32Array([rr.serial, rr.refresh, rr.retry, rr.expire, rr.minttl]));
+ break;
+ }
+ default:
+ throw new Error('Unknown RR type ' + rr.type);
+ }
+ }
+ } catch (err) {
+ _didIteratorError4 = true;
+ _iteratorError4 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion4 && _iterator4.return) {
+ _iterator4.return();
+ }
+ } finally {
+ if (_didIteratorError4) {
+ throw _iteratorError4;
+ }
+ }
+ }
+
+ return Buffer.concat(buffers.map(function (typedArray) {
+ var buf = Buffer.from(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);
+ if (os.endianness() === 'LE') {
+ if (typedArray.BYTES_PER_ELEMENT === 2) buf.swap16();
+ if (typedArray.BYTES_PER_ELEMENT === 4) buf.swap32();
+ }
+ return buf;
+ }));
+}
+
+module.exports = { types: types, classes: classes, writeDNSPacket: writeDNSPacket, parseDNSPacket: parseDNSPacket };
+
+function forEach(xs, f) {
+ for (var i = 0, l = xs.length; i < l; i++) {
+ f(xs[i], i);
+ }
+}
\ No newline at end of file
diff --git a/test/common/duplexpair.js b/test/common/duplexpair.js
new file mode 100644
index 0000000..821983d
--- /dev/null
+++ b/test/common/duplexpair.js
@@ -0,0 +1,94 @@
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+/**/
+require('babel-polyfill');
+var util = require('util');
+for (var i in util) {
+ exports[i] = util[i];
+} /**/ /**/
+if (!global.setImmediate) {
+ global.setImmediate = function setImmediate(fn) {
+ return setTimeout(fn.bind.apply(fn, arguments), 4);
+ };
+}
+if (!global.clearImmediate) {
+ global.clearImmediate = function clearImmediate(i) {
+ return clearTimeout(i);
+ };
+}
+/**/
+/* eslint-disable required-modules */
+'use strict';
+
+/**/
+var objectKeys = objectKeys || function (obj) {
+ var keys = [];
+ for (var key in obj) {
+ keys.push(key);
+ }return keys;
+};
+/**/
+
+var _require = require('stream'),
+ Duplex = _require.Duplex;
+
+var assert = require('assert');
+
+var kCallback = Symbol('Callback');
+var kOtherSide = Symbol('Other');
+
+var DuplexSocket = function (_Duplex) {
+ _inherits(DuplexSocket, _Duplex);
+
+ function DuplexSocket() {
+ _classCallCheck(this, DuplexSocket);
+
+ var _this = _possibleConstructorReturn(this, _Duplex.call(this));
+
+ _this[kCallback] = null;
+ _this[kOtherSide] = null;
+ return _this;
+ }
+
+ DuplexSocket.prototype._read = function _read() {
+ var callback = this[kCallback];
+ if (callback) {
+ this[kCallback] = null;
+ callback();
+ }
+ };
+
+ DuplexSocket.prototype._write = function _write(chunk, encoding, callback) {
+ assert.notStrictEqual(this[kOtherSide], null);
+ assert.strictEqual(this[kOtherSide][kCallback], null);
+ this[kOtherSide][kCallback] = callback;
+ this[kOtherSide].push(chunk);
+ };
+
+ DuplexSocket.prototype._final = function _final(callback) {
+ this[kOtherSide].on('end', callback);
+ this[kOtherSide].push(null);
+ };
+
+ return DuplexSocket;
+}(Duplex);
+
+function makeDuplexPair() {
+ var clientSide = new DuplexSocket();
+ var serverSide = new DuplexSocket();
+ clientSide[kOtherSide] = serverSide;
+ serverSide[kOtherSide] = clientSide;
+ return { clientSide: clientSide, serverSide: serverSide };
+}
+
+module.exports = makeDuplexPair;
+
+function forEach(xs, f) {
+ for (var i = 0, l = xs.length; i < l; i++) {
+ f(xs[i], i);
+ }
+}
\ No newline at end of file
diff --git a/test/common/fixtures.js b/test/common/fixtures.js
new file mode 100644
index 0000000..75f170d
--- /dev/null
+++ b/test/common/fixtures.js
@@ -0,0 +1,65 @@
+function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+/**/
+require('babel-polyfill');
+var util = require('util');
+for (var i in util) {
+ exports[i] = util[i];
+} /**/ /**/
+if (!global.setImmediate) {
+ global.setImmediate = function setImmediate(fn) {
+ return setTimeout(fn.bind.apply(fn, arguments), 4);
+ };
+}
+if (!global.clearImmediate) {
+ global.clearImmediate = function clearImmediate(i) {
+ return clearTimeout(i);
+ };
+}
+/**/
+/* eslint-disable required-modules */
+'use strict';
+
+/**/
+var objectKeys = objectKeys || function (obj) {
+ var keys = [];
+ for (var key in obj) {
+ keys.push(key);
+ }return keys;
+};
+/**/
+
+var path = require('path');
+var fs = require('fs');
+
+var fixturesDir = path.join(__dirname, '..', 'fixtures');
+
+function fixturesPath() {
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ return path.join.apply(path, [fixturesDir].concat(args));
+}
+
+function readFixtureSync(args, enc) {
+ if (Array.isArray(args)) return fs.readFileSync(fixturesPath.apply(undefined, _toConsumableArray(args)), enc);
+ return fs.readFileSync(fixturesPath(args), enc);
+}
+
+function readFixtureKey(name, enc) {
+ return fs.readFileSync(fixturesPath('keys', name), enc);
+}
+
+module.exports = {
+ fixturesDir: fixturesDir,
+ path: fixturesPath,
+ readSync: readFixtureSync,
+ readKey: readFixtureKey
+};
+
+function forEach(xs, f) {
+ for (var i = 0, l = xs.length; i < l; i++) {
+ f(xs[i], i);
+ }
+}
\ No newline at end of file
diff --git a/test/common/index.js b/test/common/index.js
new file mode 100644
index 0000000..ce627d1
--- /dev/null
+++ b/test/common/index.js
@@ -0,0 +1,987 @@
+function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
+
+function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+/**/
+require('babel-polyfill');
+var util = require('util');
+for (var i in util) {
+ exports[i] = util[i];
+} /**/ /**/
+if (!global.setImmediate) {
+ global.setImmediate = function setImmediate(fn) {
+ return setTimeout(fn.bind.apply(fn, arguments), 4);
+ };
+}
+if (!global.clearImmediate) {
+ global.clearImmediate = function clearImmediate(i) {
+ return clearTimeout(i);
+ };
+}
+/**/
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+/* eslint-disable required-modules, crypto-check */
+'use strict';
+
+/**/
+var objectKeys = objectKeys || function (obj) {
+ var keys = [];
+ for (var key in obj) {
+ keys.push(key);
+ }return keys;
+};
+/**/
+
+var path = require('path');
+var fs = require('fs');
+var assert = require('assert');
+var os = require('os');
+
+var _require = require('child_process'),
+ exec = _require.exec,
+ execSync = _require.execSync,
+ spawn = _require.spawn,
+ spawnSync = _require.spawnSync;
+
+var stream = require('stream');
+
+/**/
+var util = require('core-util-is');
+util.inherits = require('inherits');
+/**/
+
+var Timer = { now: function () {} };
+
+var _require2 = require('./fixtures'),
+ fixturesDir = _require2.fixturesDir;
+
+var testRoot = process.env.NODE_TEST_DIR ? fs.realpathSync(process.env.NODE_TEST_DIR) : path.resolve(__dirname, '..');
+
+var noop = function () {};
+
+// Using a `.` prefixed name, which is the convention for "hidden" on POSIX,
+// gets tools to ignore it by default or by simple rules, especially eslint.
+var tmpDirName = '.tmp';
+// PORT should match the definition in test/testpy/__init__.py.
+exports.PORT = +process.env.NODE_COMMON_PORT || 12346;
+exports.isWindows = process.platform === 'win32';
+exports.isWOW64 = exports.isWindows && process.env.PROCESSOR_ARCHITEW6432 !== undefined;
+exports.isAIX = process.platform === 'aix';
+exports.isLinuxPPCBE = process.platform === 'linux' && process.arch === 'ppc64' && os.endianness() === 'BE';
+exports.isSunOS = process.platform === 'sunos';
+exports.isFreeBSD = process.platform === 'freebsd';
+exports.isLinux = process.platform === 'linux';
+exports.isOSX = process.platform === 'darwin';
+
+exports.enoughTestMem = os.totalmem() > 0x70000000; /* 1.75 Gb */
+var cpus = os.cpus();
+/*exports.enoughTestCpu = Array.isArray(cpus) &&
+ (cpus.length > 1 || cpus[0].speed > 999);*/
+
+exports.rootDir = exports.isWindows ? 'c:\\' : '/';
+exports.projectDir = path.resolve(__dirname, '..', '..');
+
+//exports.buildType = process.config.target_defaults.default_configuration;
+
+// Always enable async_hooks checks in tests
+{
+ // const async_wrap = process.binding('async_wrap');
+ // const kCheck = async_wrap.constants.kCheck;
+ // async_wrap.async_hook_fields[kCheck] += 1;
+
+ exports.revert_force_async_hooks_checks = function () {
+ async_wrap.async_hook_fields[kCheck] -= 1;
+ };
+}
+
+// If env var is set then enable async_hook hooks for all tests.
+if (process.env.NODE_TEST_WITH_ASYNC_HOOKS) {
+ var destroydIdsList = {};
+ var destroyListList = {};
+ var initHandles = {};
+ var _async_wrap = process.binding('async_wrap');
+
+ process.on('exit', function () {
+ // itterate through handles to make sure nothing crashes
+ for (var k in initHandles) {
+ util.inspect(initHandles[k]);
+ }
+ });
+
+ var _queueDestroyAsyncId = _async_wrap.queueDestroyAsyncId;
+ _async_wrap.queueDestroyAsyncId = function queueDestroyAsyncId(id) {
+ if (destroyListList[id] !== undefined) {
+ process._rawDebug(destroyListList[id]);
+ process._rawDebug();
+ throw new Error('same id added to destroy list twice (' + id + ')');
+ }
+ destroyListList[id] = new Error().stack;
+ _queueDestroyAsyncId(id);
+ };
+
+ /*require('async_hooks').createHook({
+ init(id, ty, tr, r) {
+ if (initHandles[id]) {
+ process._rawDebug(
+ `Is same resource: ${r === initHandles[id].resource}`);
+ process._rawDebug(`Previous stack:\n${initHandles[id].stack}\n`);
+ throw new Error(`init called twice for same id (${id})`);
+ }
+ initHandles[id] = { resource: r, stack: new Error().stack.substr(6) };
+ },
+ before() { },
+ after() { },
+ destroy(id) {
+ if (destroydIdsList[id] !== undefined) {
+ process._rawDebug(destroydIdsList[id]);
+ process._rawDebug();
+ throw new Error(`destroy called for same id (${id})`);
+ }
+ destroydIdsList[id] = new Error().stack;
+ },
+ }).enable();*/
+}
+
+function rimrafSync(p) {
+ var st = void 0;
+ try {
+ st = fs.lstatSync(p);
+ } catch (e) {
+ if (e.code === 'ENOENT') return;
+ }
+
+ try {
+ if (st && st.isDirectory()) rmdirSync(p, null);else fs.unlinkSync(p);
+ } catch (e) {
+ if (e.code === 'ENOENT') return;
+ if (e.code === 'EPERM') return rmdirSync(p, e);
+ if (e.code !== 'EISDIR') throw e;
+ rmdirSync(p, e);
+ }
+}
+
+function rmdirSync(p, originalEr) {
+ try {
+ fs.rmdirSync(p);
+ } catch (e) {
+ if (e.code === 'ENOTDIR') throw originalEr;
+ if (e.code === 'ENOTEMPTY' || e.code === 'EEXIST' || e.code === 'EPERM') {
+ var enc = exports.isLinux ? 'buffer' : 'utf8';
+ forEach(fs.readdirSync(p, enc), function (f) {
+ if (f instanceof Buffer) {
+ var buf = Buffer.concat([Buffer.from(p), Buffer.from(path.sep), f]);
+ rimrafSync(buf);
+ } else {
+ rimrafSync(path.join(p, f));
+ }
+ });
+ fs.rmdirSync(p);
+ }
+ }
+}
+
+exports.refreshTmpDir = function () {
+ rimrafSync(exports.tmpDir);
+ fs.mkdirSync(exports.tmpDir);
+};
+
+if (process.env.TEST_THREAD_ID) {
+ exports.PORT += process.env.TEST_THREAD_ID * 100;
+ tmpDirName += '.' + process.env.TEST_THREAD_ID;
+}
+exports.tmpDir = path.join(testRoot, tmpDirName);
+
+var opensslCli = null;
+var inFreeBSDJail = null;
+var localhostIPv4 = null;
+
+exports.localIPv6Hosts = ['localhost'];
+if (exports.isLinux) {
+ exports.localIPv6Hosts = [
+ // Debian/Ubuntu
+ 'ip6-localhost', 'ip6-loopback',
+
+ // SUSE
+ 'ipv6-localhost', 'ipv6-loopback',
+
+ // Typically universal
+ 'localhost'];
+}
+
+/**/if (!process.browser) {
+ Object.defineProperty(exports, 'inFreeBSDJail', {
+ get: function () {
+ if (inFreeBSDJail !== null) return inFreeBSDJail;
+
+ if (exports.isFreeBSD && execSync('sysctl -n security.jail.jailed').toString() === '1\n') {
+ inFreeBSDJail = true;
+ } else {
+ inFreeBSDJail = false;
+ }
+ return inFreeBSDJail;
+ }
+ });
+} /**/
+
+/**/if (!process.browser) {
+ Object.defineProperty(exports, 'localhostIPv4', {
+ get: function () {
+ if (localhostIPv4 !== null) return localhostIPv4;
+
+ if (exports.inFreeBSDJail) {
+ // Jailed network interfaces are a bit special - since we need to jump
+ // through loops, as well as this being an exception case, assume the
+ // user will provide this instead.
+ if (process.env.LOCALHOST) {
+ localhostIPv4 = process.env.LOCALHOST;
+ } else {
+ console.error('Looks like we\'re in a FreeBSD Jail. ' + 'Please provide your default interface address ' + 'as LOCALHOST or expect some tests to fail.');
+ }
+ }
+
+ if (localhostIPv4 === null) localhostIPv4 = '127.0.0.1';
+
+ return localhostIPv4;
+ }
+ });
+} /**/
+
+// opensslCli defined lazily to reduce overhead of spawnSync
+/**/if (!process.browser) {
+ Object.defineProperty(exports, 'opensslCli', { get: function () {
+ if (opensslCli !== null) return opensslCli;
+
+ if (process.config.variables.node_shared_openssl) {
+ // use external command
+ opensslCli = 'openssl';
+ } else {
+ // use command built from sources included in Node.js repository
+ opensslCli = path.join(path.dirname(process.execPath), 'openssl-cli');
+ }
+
+ if (exports.isWindows) opensslCli += '.exe';
+
+ var opensslCmd = spawnSync(opensslCli, ['version']);
+ if (opensslCmd.status !== 0 || opensslCmd.error !== undefined) {
+ // openssl command cannot be executed
+ opensslCli = false;
+ }
+ return opensslCli;
+ }, enumerable: true });
+} /**/
+
+/**/if (!process.browser) {
+ Object.defineProperty(exports, 'hasCrypto', {
+ get: function () {
+ return Boolean(process.versions.openssl);
+ }
+ });
+} /**/
+
+/**/if (!process.browser) {
+ Object.defineProperty(exports, 'hasFipsCrypto', {
+ get: function () {
+ return exports.hasCrypto && require('crypto').fips;
+ }
+ });
+} /**/
+
+{
+ var localRelative = path.relative(process.cwd(), exports.tmpDir + '/');
+ var pipePrefix = exports.isWindows ? '\\\\.\\pipe\\' : localRelative;
+ var pipeName = 'node-test.' + process.pid + '.sock';
+ exports.PIPE = path.join(pipePrefix, pipeName);
+}
+
+{
+ var iFaces = os.networkInterfaces();
+ var re = exports.isWindows ? /Loopback Pseudo-Interface/ : /lo/;
+ exports.hasIPv6 = objectKeys(iFaces).some(function (name) {
+ return re.test(name) && iFaces[name].some(function (info) {
+ return info.family === 'IPv6';
+ });
+ });
+}
+
+/*
+ * Check that when running a test with
+ * `$node --abort-on-uncaught-exception $file child`
+ * the process aborts.
+ */
+exports.childShouldThrowAndAbort = function () {
+ var testCmd = '';
+ if (!exports.isWindows) {
+ // Do not create core files, as it can take a lot of disk space on
+ // continuous testing and developers' machines
+ testCmd += 'ulimit -c 0 && ';
+ }
+ testCmd += '"' + process.argv[0] + '" --abort-on-uncaught-exception ';
+ testCmd += '"' + process.argv[1] + '" child';
+ var child = exec(testCmd);
+ child.on('exit', function onExit(exitCode, signal) {
+ var errMsg = 'Test should have aborted ' + ('but instead exited with exit code ' + exitCode) + (' and signal ' + signal);
+ assert(exports.nodeProcessAborted(exitCode, signal), errMsg);
+ });
+};
+
+exports.ddCommand = function (filename, kilobytes) {
+ if (exports.isWindows) {
+ var p = path.resolve(fixturesDir, 'create-file.js');
+ return '"' + process.argv[0] + '" "' + p + '" "' + filename + '" ' + kilobytes * 1024;
+ } else {
+ return 'dd if=/dev/zero of="' + filename + '" bs=1024 count=' + kilobytes;
+ }
+};
+
+exports.spawnPwd = function (options) {
+ if (exports.isWindows) {
+ return spawn('cmd.exe', ['/d', '/c', 'cd'], options);
+ } else {
+ return spawn('pwd', [], options);
+ }
+};
+
+exports.spawnSyncPwd = function (options) {
+ if (exports.isWindows) {
+ return spawnSync('cmd.exe', ['/d', '/c', 'cd'], options);
+ } else {
+ return spawnSync('pwd', [], options);
+ }
+};
+
+exports.platformTimeout = function (ms) {
+ if (process.features.debug) ms = 2 * ms;
+
+ if (global.__coverage__) ms = 4 * ms;
+
+ if (exports.isAIX) return 2 * ms; // default localhost speed is slower on AIX
+
+ if (process.arch !== 'arm') return ms;
+
+ var armv = process.config.variables.arm_version;
+
+ if (armv === '6') return 7 * ms; // ARMv6
+
+ if (armv === '7') return 2 * ms; // ARMv7
+
+ return ms; // ARMv8+
+};
+
+var knownGlobals = [Buffer, clearImmediate, clearInterval, clearTimeout, console, constructor, // Enumerable in V8 3.21.
+global, process, setImmediate, setInterval, setTimeout];
+
+if (global.gc) {
+ knownGlobals.push(global.gc);
+}
+
+if (global.DTRACE_HTTP_SERVER_RESPONSE) {
+ knownGlobals.push(DTRACE_HTTP_SERVER_RESPONSE);
+ knownGlobals.push(DTRACE_HTTP_SERVER_REQUEST);
+ knownGlobals.push(DTRACE_HTTP_CLIENT_RESPONSE);
+ knownGlobals.push(DTRACE_HTTP_CLIENT_REQUEST);
+ knownGlobals.push(DTRACE_NET_STREAM_END);
+ knownGlobals.push(DTRACE_NET_SERVER_CONNECTION);
+}
+
+if (global.COUNTER_NET_SERVER_CONNECTION) {
+ knownGlobals.push(COUNTER_NET_SERVER_CONNECTION);
+ knownGlobals.push(COUNTER_NET_SERVER_CONNECTION_CLOSE);
+ knownGlobals.push(COUNTER_HTTP_SERVER_REQUEST);
+ knownGlobals.push(COUNTER_HTTP_SERVER_RESPONSE);
+ knownGlobals.push(COUNTER_HTTP_CLIENT_REQUEST);
+ knownGlobals.push(COUNTER_HTTP_CLIENT_RESPONSE);
+}
+
+if (global.LTTNG_HTTP_SERVER_RESPONSE) {
+ knownGlobals.push(LTTNG_HTTP_SERVER_RESPONSE);
+ knownGlobals.push(LTTNG_HTTP_SERVER_REQUEST);
+ knownGlobals.push(LTTNG_HTTP_CLIENT_RESPONSE);
+ knownGlobals.push(LTTNG_HTTP_CLIENT_REQUEST);
+ knownGlobals.push(LTTNG_NET_STREAM_END);
+ knownGlobals.push(LTTNG_NET_SERVER_CONNECTION);
+}
+
+/**/if (!process.browser) {
+ if (global.ArrayBuffer) {
+ knownGlobals.push(ArrayBuffer);
+ knownGlobals.push(Int8Array);
+ knownGlobals.push(Uint8Array);
+ knownGlobals.push(Uint8ClampedArray);
+ knownGlobals.push(Int16Array);
+ knownGlobals.push(Uint16Array);
+ knownGlobals.push(Int32Array);
+ knownGlobals.push(Uint32Array);
+ knownGlobals.push(Float32Array);
+ knownGlobals.push(Float64Array);
+ knownGlobals.push(DataView);
+ }
+} /**/
+
+// Harmony features.
+if (global.Proxy) {
+ knownGlobals.push(Proxy);
+}
+
+if (global.Symbol) {
+ knownGlobals.push(Symbol);
+}
+
+if (process.env.NODE_TEST_KNOWN_GLOBALS) {
+ var knownFromEnv = process.env.NODE_TEST_KNOWN_GLOBALS.split(',');
+ allowGlobals.apply(undefined, _toConsumableArray(knownFromEnv));
+}
+
+function allowGlobals() {
+ for (var _len = arguments.length, whitelist = Array(_len), _key = 0; _key < _len; _key++) {
+ whitelist[_key] = arguments[_key];
+ }
+
+ knownGlobals = knownGlobals.concat(whitelist);
+}
+exports.allowGlobals = allowGlobals;
+
+/**/
+if (typeof constructor == 'function') knownGlobals.push(constructor);
+if (typeof DTRACE_NET_SOCKET_READ == 'function') knownGlobals.push(DTRACE_NET_SOCKET_READ);
+if (typeof DTRACE_NET_SOCKET_WRITE == 'function') knownGlobals.push(DTRACE_NET_SOCKET_WRITE);
+if (global.__coverage__) knownGlobals.push(__coverage__);
+'core,__core-js_shared__,Promise,Map,Set,WeakMap,WeakSet,Reflect,System,asap,Observable,regeneratorRuntime,_babelPolyfill'.split(',').filter(function (item) {
+ return typeof global[item] !== undefined;
+}).forEach(function (item) {
+ knownGlobals.push(global[item]);
+}); /**/
+
+function leakedGlobals() {
+ var leaked = [];
+
+ for (var val in global) {
+ if (!knownGlobals.includes(global[val])) {
+ leaked.push(val);
+ }
+ }
+
+ if (global.__coverage__) {
+ return leaked.filter(function (varname) {
+ return !/^(?:cov_|__cov)/.test(varname);
+ });
+ } else {
+ return leaked;
+ }
+}
+exports.leakedGlobals = leakedGlobals;
+
+// Turn this off if the test should not check for global leaks.
+exports.globalCheck = true;
+
+process.on('exit', function () {
+ if (!exports.globalCheck) return;
+ var leaked = leakedGlobals();
+ if (leaked.length > 0) {
+ assert.fail('Unexpected global(s) found: ' + leaked.join(', '));
+ }
+});
+
+var mustCallChecks = [];
+
+function runCallChecks(exitCode) {
+ if (exitCode !== 0) return;
+
+ var failed = mustCallChecks.filter(function (context) {
+ if ('minimum' in context) {
+ context.messageSegment = 'at least ' + context.minimum;
+ return context.actual < context.minimum;
+ } else {
+ context.messageSegment = 'exactly ' + context.exact;
+ return context.actual !== context.exact;
+ }
+ });
+
+ forEach(failed, function (context) {
+ console.log('Mismatched %s function calls. Expected %s, actual %d.', context.name, context.messageSegment, context.actual);
+ console.log(context.stack.split('\n').slice(2).join('\n'));
+ });
+
+ if (failed.length) process.exit(1);
+}
+
+exports.mustCall = function (fn, exact) {
+ return _mustCallInner(fn, exact, 'exact');
+};
+
+exports.mustCallAtLeast = function (fn, minimum) {
+ return _mustCallInner(fn, minimum, 'minimum');
+};
+
+function _mustCallInner(fn) {
+ var _context;
+
+ var criteria = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
+ var field = arguments[2];
+
+ if (process._exiting) throw new Error('Cannot use common.mustCall*() in process exit handler');
+ if (typeof fn === 'number') {
+ criteria = fn;
+ fn = noop;
+ } else if (fn === undefined) {
+ fn = noop;
+ }
+
+ if (typeof criteria !== 'number') throw new TypeError('Invalid ' + field + ' value: ' + criteria);
+
+ var context = (_context = {}, _defineProperty(_context, field, criteria), _defineProperty(_context, 'actual', 0), _defineProperty(_context, 'stack', new Error().stack), _defineProperty(_context, 'name', fn.name || ''), _context);
+
+ // add the exit listener only once to avoid listener leak warnings
+ if (mustCallChecks.length === 0) process.on('exit', runCallChecks);
+
+ mustCallChecks.push(context);
+
+ return function () {
+ context.actual++;
+ return fn.apply(this, arguments);
+ };
+}
+
+exports.hasMultiLocalhost = function hasMultiLocalhost() {
+ var TCP = process.binding('tcp_wrap').TCP;
+ var t = new TCP();
+ var ret = t.bind('127.0.0.2', 0);
+ t.close();
+ return ret === 0;
+};
+
+exports.fileExists = function (pathname) {
+ try {
+ fs.accessSync(pathname);
+ return true;
+ } catch (err) {
+ return false;
+ }
+};
+
+exports.canCreateSymLink = function () {
+ // On Windows, creating symlinks requires admin privileges.
+ // We'll only try to run symlink test if we have enough privileges.
+ // On other platforms, creating symlinks shouldn't need admin privileges
+ if (exports.isWindows) {
+ // whoami.exe needs to be the one from System32
+ // If unix tools are in the path, they can shadow the one we want,
+ // so use the full path while executing whoami
+ var whoamiPath = path.join(process.env['SystemRoot'], 'System32', 'whoami.exe');
+
+ var err = false;
+ var output = '';
+
+ try {
+ output = execSync(whoamiPath + ' /priv', { timout: 1000 });
+ } catch (e) {
+ err = true;
+ } finally {
+ if (err || !output.includes('SeCreateSymbolicLinkPrivilege')) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+};
+
+exports.getCallSite = function getCallSite(top) {
+ var originalStackFormatter = Error.prepareStackTrace;
+ Error.prepareStackTrace = function (err, stack) {
+ return stack[0].getFileName() + ':' + stack[0].getLineNumber();
+ };
+ var err = new Error();
+ Error.captureStackTrace(err, top);
+ // with the V8 Error API, the stack is not formatted until it is accessed
+ err.stack;
+ Error.prepareStackTrace = originalStackFormatter;
+ return err.stack;
+};
+
+exports.mustNotCall = function (msg) {
+ var callSite = exports.getCallSite(exports.mustNotCall);
+ return function mustNotCall() {
+ assert.fail((msg || 'function should not have been called') + ' at ' + callSite);
+ };
+};
+
+exports.printSkipMessage = function (msg) {
+ console.log('1..0 # Skipped: ' + msg);
+};
+
+exports.skip = function (msg) {
+ exports.printSkipMessage(msg);
+ process.exit(0);
+};
+
+// A stream to push an array into a REPL
+function ArrayStream() {
+ this.run = function (data) {
+ var _this = this;
+
+ forEach(data, function (line) {
+ _this.emit('data', line + '\n');
+ });
+ };
+}
+
+util.inherits(ArrayStream, stream.Stream);
+exports.ArrayStream = ArrayStream;
+ArrayStream.prototype.readable = true;
+ArrayStream.prototype.writable = true;
+ArrayStream.prototype.pause = noop;
+ArrayStream.prototype.resume = noop;
+ArrayStream.prototype.write = noop;
+
+// Returns true if the exit code "exitCode" and/or signal name "signal"
+// represent the exit code and/or signal name of a node process that aborted,
+// false otherwise.
+exports.nodeProcessAborted = function nodeProcessAborted(exitCode, signal) {
+ // Depending on the compiler used, node will exit with either
+ // exit code 132 (SIGILL), 133 (SIGTRAP) or 134 (SIGABRT).
+ var expectedExitCodes = [132, 133, 134];
+
+ // On platforms using KSH as the default shell (like SmartOS),
+ // when a process aborts, KSH exits with an exit code that is
+ // greater than 256, and thus the exit code emitted with the 'exit'
+ // event is null and the signal is set to either SIGILL, SIGTRAP,
+ // or SIGABRT (depending on the compiler).
+ var expectedSignals = ['SIGILL', 'SIGTRAP', 'SIGABRT'];
+
+ // On Windows, 'aborts' are of 2 types, depending on the context:
+ // (i) Forced access violation, if --abort-on-uncaught-exception is on
+ // which corresponds to exit code 3221225477 (0xC0000005)
+ // (ii) raise(SIGABRT) or abort(), which lands up in CRT library calls
+ // which corresponds to exit code 3.
+ if (exports.isWindows) expectedExitCodes = [3221225477, 3];
+
+ // When using --abort-on-uncaught-exception, V8 will use
+ // base::OS::Abort to terminate the process.
+ // Depending on the compiler used, the shell or other aspects of
+ // the platform used to build the node binary, this will actually
+ // make V8 exit by aborting or by raising a signal. In any case,
+ // one of them (exit code or signal) needs to be set to one of
+ // the expected exit codes or signals.
+ if (signal !== null) {
+ return expectedSignals.includes(signal);
+ } else {
+ return expectedExitCodes.includes(exitCode);
+ }
+};
+
+exports.busyLoop = function busyLoop(time) {
+ var startTime = Timer.now();
+ var stopTime = startTime + time;
+ while (Timer.now() < stopTime) {}
+};
+
+exports.isAlive = function isAlive(pid) {
+ try {
+ process.kill(pid, 'SIGCONT');
+ return true;
+ } catch (e) {
+ return false;
+ }
+};
+
+function expectWarning(name, expectedMessages) {
+ return exports.mustCall(function (warning) {
+ assert.strictEqual(warning.name, name);
+ assert.ok(expectedMessages.includes(warning.message), 'unexpected error message: "' + warning.message + '"');
+ // Remove a warning message after it is seen so that we guarantee that we
+ // get each message only once.
+ expectedMessages.splice(expectedMessages.indexOf(warning.message), 1);
+ }, expectedMessages.length);
+}
+
+function expectWarningByName(name, expected) {
+ if (typeof expected === 'string') {
+ expected = [expected];
+ }
+ process.on('warning', expectWarning(name, expected));
+}
+
+function expectWarningByMap(warningMap) {
+ var catchWarning = {};
+ forEach(objectKeys(warningMap), function (name) {
+ var expected = warningMap[name];
+ if (typeof expected === 'string') {
+ expected = [expected];
+ }
+ catchWarning[name] = expectWarning(name, expected);
+ });
+ process.on('warning', function (warning) {
+ return catchWarning[warning.name](warning);
+ });
+}
+
+// accepts a warning name and description or array of descriptions or a map
+// of warning names to description(s)
+// ensures a warning is generated for each name/description pair
+exports.expectWarning = function (nameOrMap, expected) {
+ if (typeof nameOrMap === 'string') {
+ expectWarningByName(nameOrMap, expected);
+ } else {
+ expectWarningByMap(nameOrMap);
+ }
+};
+
+/**/if (!process.browser) {
+ Object.defineProperty(exports, 'hasIntl', {
+ get: function () {
+ return process.binding('config').hasIntl;
+ }
+ });
+} /**/
+
+/**/if (!process.browser) {
+ Object.defineProperty(exports, 'hasSmallICU', {
+ get: function () {
+ return process.binding('config').hasSmallICU;
+ }
+ });
+} /**/
+
+// Useful for testing expected internal/error objects
+exports.expectsError = function expectsError(fn, settings, exact) {
+ if (typeof fn !== 'function') {
+ exact = settings;
+ settings = fn;
+ fn = undefined;
+ }
+ var innerFn = exports.mustCall(function (error) {
+ assert.strictEqual(error.code, settings.code);
+ if ('type' in settings) {
+ var type = settings.type;
+ if (type !== Error && !Error.isPrototypeOf(type)) {
+ throw new TypeError('`settings.type` must inherit from `Error`');
+ }
+ assert(error instanceof type, error.name + ' is not instance of ' + type.name);
+ }
+ if ('message' in settings) {
+ var message = settings.message;
+ if (typeof message === 'string') {
+ assert.strictEqual(error.message, message);
+ } else {
+ assert(message.test(error.message), error.message + ' does not match ' + message);
+ }
+ }
+ if ('name' in settings) {
+ assert.strictEqual(error.name, settings.name);
+ }
+ if (error.constructor.name === 'AssertionError') {
+ forEach(['generatedMessage', 'actual', 'expected', 'operator'], function (key) {
+ if (key in settings) {
+ var actual = error[key];
+ var expected = settings[key];
+ assert.strictEqual(actual, expected, key + ': expected ' + expected + ', not ' + actual);
+ }
+ });
+ }
+ return true;
+ }, exact);
+ if (fn) {
+ assert.throws(fn, innerFn);
+ return;
+ }
+ return innerFn;
+};
+
+exports.skipIfInspectorDisabled = function skipIfInspectorDisabled() {
+ if (process.config.variables.v8_enable_inspector === 0) {
+ exports.skip('V8 inspector is disabled');
+ }
+};
+
+exports.skipIf32Bits = function skipIf32Bits() {
+ if (process.binding('config').bits < 64) {
+ exports.skip('The tested feature is not available in 32bit builds');
+ }
+};
+
+var arrayBufferViews = [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array, DataView];
+
+exports.getArrayBufferViews = function getArrayBufferViews(buf) {
+ var buffer = buf.buffer,
+ byteOffset = buf.byteOffset,
+ byteLength = buf.byteLength;
+
+
+ var out = [];
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = arrayBufferViews[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ var type = _step.value;
+ var _type$BYTES_PER_ELEME = type.BYTES_PER_ELEMENT,
+ BYTES_PER_ELEMENT = _type$BYTES_PER_ELEME === undefined ? 1 : _type$BYTES_PER_ELEME;
+
+ if (byteLength % BYTES_PER_ELEMENT === 0) {
+ out.push(new type(buffer, byteOffset, byteLength / BYTES_PER_ELEMENT));
+ }
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+
+ return out;
+};
+
+// Crash the process on unhandled rejections.
+exports.crashOnUnhandledRejection = function () {
+ process.on('unhandledRejection', function (err) {
+ return process.nextTick(function () {
+ throw err;
+ });
+ });
+};
+
+exports.getTTYfd = function getTTYfd() {
+ var tty = require('tty');
+ var tty_fd = 0;
+ if (!tty.isatty(tty_fd)) tty_fd++;else if (!tty.isatty(tty_fd)) tty_fd++;else if (!tty.isatty(tty_fd)) tty_fd++;else {
+ try {
+ tty_fd = fs.openSync('/dev/tty');
+ } catch (e) {
+ // There aren't any tty fd's available to use.
+ return -1;
+ }
+ }
+ return tty_fd;
+};
+
+// Hijack stdout and stderr
+var stdWrite = {};
+function hijackStdWritable(name, listener) {
+ var stream = process[name];
+ var _write = stdWrite[name] = stream.write;
+
+ stream.writeTimes = 0;
+ stream.write = function (data, callback) {
+ try {
+ listener(data);
+ } catch (e) {
+ process.nextTick(function () {
+ throw e;
+ });
+ }
+
+ _write.call(stream, data, callback);
+ stream.writeTimes++;
+ };
+}
+
+function restoreWritable(name) {
+ process[name].write = stdWrite[name];
+ delete process[name].writeTimes;
+}
+
+function onResolvedOrRejected(promise, callback) {
+ return promise.then(function (result) {
+ callback();
+ return result;
+ }, function (error) {
+ callback();
+ throw error;
+ });
+}
+
+function timeoutPromise(error, timeoutMs) {
+ var clearCallback = null;
+ var done = false;
+ var promise = onResolvedOrRejected(new Promise(function (resolve, reject) {
+ var timeout = setTimeout(function () {
+ return reject(error);
+ }, timeoutMs);
+ clearCallback = function () {
+ if (done) return;
+ clearTimeout(timeout);
+ resolve();
+ };
+ }), function () {
+ return done = true;
+ });
+ promise.clear = clearCallback;
+ return promise;
+}
+
+exports.hijackStdout = hijackStdWritable.bind(null, 'stdout');
+exports.hijackStderr = hijackStdWritable.bind(null, 'stderr');
+exports.restoreStdout = restoreWritable.bind(null, 'stdout');
+exports.restoreStderr = restoreWritable.bind(null, 'stderr');
+
+var fd = 2;
+exports.firstInvalidFD = function firstInvalidFD() {
+ // Get first known bad file descriptor.
+ try {
+ while (fs.fstatSync(++fd)) {}
+ } catch (e) {}
+ return fd;
+};
+
+exports.fires = function fires(promise, error, timeoutMs) {
+ if (!timeoutMs && util.isNumber(error)) {
+ timeoutMs = error;
+ error = null;
+ }
+ if (!error) error = 'timeout';
+ if (!timeoutMs) timeoutMs = 100;
+ var timeout = timeoutPromise(error, timeoutMs);
+ return Promise.race([onResolvedOrRejected(promise, function () {
+ return timeout.clear();
+ }), timeout]);
+};
+
+function forEach(xs, f) {
+ for (var i = 0, l = xs.length; i < l; i++) {
+ f(xs[i], i);
+ }
+}
+
+if (!util._errnoException) {
+ var uv;
+ util._errnoException = function (err, syscall) {
+ if (util.isUndefined(uv)) try {
+ uv = process.binding('uv');
+ } catch (e) {}
+ var errname = uv ? uv.errname(err) : '';
+ var e = new Error(syscall + ' ' + errname);
+ e.code = errname;
+ e.errno = errname;
+ e.syscall = syscall;
+ return e;
+ };
+}
\ No newline at end of file
diff --git a/test/common/index.mjs b/test/common/index.mjs
new file mode 100644
index 0000000..ad89e9d
--- /dev/null
+++ b/test/common/index.mjs
@@ -0,0 +1,131 @@
+/**/
+ require('babel-polyfill');
+ var util = require('util');
+ for (var i in util) exports[i] = util[i];
+ /**//**/
+if (!global.setImmediate) {
+ global.setImmediate = function setImmediate(fn) {
+ return setTimeout(fn.bind.apply(fn, arguments), 4);
+ };
+}
+if (!global.clearImmediate) {
+ global.clearImmediate = function clearImmediate(i) {
+ return clearTimeout(i);
+ };
+}
+/**/
+// Flags: --experimental-modules
+/* eslint-disable required-modules */
+
+import assert from 'assert';
+
+let knownGlobals = [
+ Buffer,
+ clearImmediate,
+ clearInterval,
+ clearTimeout,
+ console,
+ constructor, // Enumerable in V8 3.21.
+ global,
+ process,
+ setImmediate,
+ setInterval,
+ setTimeout
+];
+
+if (process.env.NODE_TEST_KNOWN_GLOBALS) {
+ const knownFromEnv = process.env.NODE_TEST_KNOWN_GLOBALS.split(',');
+ allowGlobals(...knownFromEnv);
+}
+
+export function allowGlobals(...whitelist) {
+ knownGlobals = knownGlobals.concat(whitelist);
+}
+
+export function leakedGlobals() {
+ //add possible expected globals
+ if (global.gc) {
+ knownGlobals.push(global.gc);
+ }
+
+ if (global.DTRACE_HTTP_SERVER_RESPONSE) {
+ knownGlobals.push(DTRACE_HTTP_SERVER_RESPONSE);
+ knownGlobals.push(DTRACE_HTTP_SERVER_REQUEST);
+ knownGlobals.push(DTRACE_HTTP_CLIENT_RESPONSE);
+ knownGlobals.push(DTRACE_HTTP_CLIENT_REQUEST);
+ knownGlobals.push(DTRACE_NET_STREAM_END);
+ knownGlobals.push(DTRACE_NET_SERVER_CONNECTION);
+ }
+
+ if (global.COUNTER_NET_SERVER_CONNECTION) {
+ knownGlobals.push(COUNTER_NET_SERVER_CONNECTION);
+ knownGlobals.push(COUNTER_NET_SERVER_CONNECTION_CLOSE);
+ knownGlobals.push(COUNTER_HTTP_SERVER_REQUEST);
+ knownGlobals.push(COUNTER_HTTP_SERVER_RESPONSE);
+ knownGlobals.push(COUNTER_HTTP_CLIENT_REQUEST);
+ knownGlobals.push(COUNTER_HTTP_CLIENT_RESPONSE);
+ }
+
+ if (global.LTTNG_HTTP_SERVER_RESPONSE) {
+ knownGlobals.push(LTTNG_HTTP_SERVER_RESPONSE);
+ knownGlobals.push(LTTNG_HTTP_SERVER_REQUEST);
+ knownGlobals.push(LTTNG_HTTP_CLIENT_RESPONSE);
+ knownGlobals.push(LTTNG_HTTP_CLIENT_REQUEST);
+ knownGlobals.push(LTTNG_NET_STREAM_END);
+ knownGlobals.push(LTTNG_NET_SERVER_CONNECTION);
+ }
+
+ if (global.ArrayBuffer) {
+ knownGlobals.push(ArrayBuffer);
+ knownGlobals.push(Int8Array);
+ knownGlobals.push(Uint8Array);
+ knownGlobals.push(Uint8ClampedArray);
+ knownGlobals.push(Int16Array);
+ knownGlobals.push(Uint16Array);
+ knownGlobals.push(Int32Array);
+ knownGlobals.push(Uint32Array);
+ knownGlobals.push(Float32Array);
+ knownGlobals.push(Float64Array);
+ knownGlobals.push(DataView);
+ }
+
+ // Harmony features.
+ if (global.Proxy) {
+ knownGlobals.push(Proxy);
+ }
+
+ if (global.Symbol) {
+ knownGlobals.push(Symbol);
+ }
+
+ const leaked = [];
+
+ for (const val in global) {
+ if (!knownGlobals.includes(global[val])) {
+ leaked.push(val);
+ }
+ }
+
+ if (global.__coverage__) {
+ return leaked.filter((varname) => !/^(?:cov_|__cov)/.test(varname));
+ } else {
+ return leaked;
+ }
+}
+
+// Turn this off if the test should not check for global leaks.
+export let globalCheck = true; // eslint-disable-line
+
+process.on('exit', function() {
+ if (!globalCheck) return;
+ const leaked = leakedGlobals();
+ if (leaked.length > 0) {
+ assert.fail(`Unexpected global(s) found: ${leaked.join(', ')}`);
+ }
+});
+
+function forEach (xs, f) {
+ for (var i = 0, l = xs.length; i < l; i++) {
+ f(xs[i], i);
+ }
+}
diff --git a/test/common/inspector-helper.js b/test/common/inspector-helper.js
new file mode 100644
index 0000000..6f3e818
--- /dev/null
+++ b/test/common/inspector-helper.js
@@ -0,0 +1,521 @@
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**/
+require('babel-polyfill');
+var util = require('util');
+for (var i in util) {
+ exports[i] = util[i];
+} /**/ /**/
+if (!global.setImmediate) {
+ global.setImmediate = function setImmediate(fn) {
+ return setTimeout(fn.bind.apply(fn, arguments), 4);
+ };
+}
+if (!global.clearImmediate) {
+ global.clearImmediate = function clearImmediate(i) {
+ return clearTimeout(i);
+ };
+}
+/**/
+'use strict';
+
+/**/
+var objectKeys = objectKeys || function (obj) {
+ var keys = [];
+ for (var key in obj) {
+ keys.push(key);
+ }return keys;
+};
+/**/
+
+var common = require('../common');
+var assert = require('assert');
+var fs = require('fs');
+var http = require('http');
+var fixtures = require('../common/fixtures');
+
+var _require = require('child_process'),
+ spawn = _require.spawn;
+
+var url = require('url');
+
+var _MAINSCRIPT = fixtures.path('loop.js');
+var DEBUG = false;
+var TIMEOUT = common.platformTimeout(15 * 1000);
+
+function spawnChildProcess(inspectorFlags, scriptContents, scriptFile) {
+ var args = [].concat(inspectorFlags);
+ if (scriptContents) {
+ args.push('-e', scriptContents);
+ } else {
+ args.push(scriptFile);
+ }
+ var child = spawn(process.execPath, args);
+
+ var handler = tearDown.bind(null, child);
+ process.on('exit', handler);
+ process.on('uncaughtException', handler);
+ process.on('unhandledRejection', handler);
+ process.on('SIGINT', handler);
+
+ return child;
+}
+
+function makeBufferingDataCallback(dataCallback) {
+ var buffer = Buffer.alloc(0);
+ return function (data) {
+ var newData = Buffer.concat([buffer, data]);
+ var str = newData.toString('utf8');
+ var lines = str.replace(/\r/g, '').split('\n');
+ if (str.endsWith('\n')) buffer = Buffer.alloc(0);else buffer = Buffer.from(lines.pop(), 'utf8');
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = lines[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ var line = _step.value;
+
+ dataCallback(line);
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+ };
+}
+
+function tearDown(child, err) {
+ child.kill();
+ if (err) {
+ console.error(err);
+ process.exit(1);
+ }
+}
+
+function parseWSFrame(buffer) {
+ // Protocol described in https://tools.ietf.org/html/rfc6455#section-5
+ var message = null;
+ if (buffer.length < 2) return { length: 0, message: message };
+ if (buffer[0] === 0x88 && buffer[1] === 0x00) {
+ return { length: 2, message: message, closed: true };
+ }
+ assert.strictEqual(0x81, buffer[0]);
+ var dataLen = 0x7F & buffer[1];
+ var bodyOffset = 2;
+ if (buffer.length < bodyOffset + dataLen) return 0;
+ if (dataLen === 126) {
+ dataLen = buffer.readUInt16BE(2);
+ bodyOffset = 4;
+ } else if (dataLen === 127) {
+ assert(buffer[2] === 0 && buffer[3] === 0, 'Inspector message too big');
+ dataLen = buffer.readUIntBE(4, 6);
+ bodyOffset = 10;
+ }
+ if (buffer.length < bodyOffset + dataLen) return { length: 0, message: message };
+ var jsonPayload = buffer.slice(bodyOffset, bodyOffset + dataLen).toString('utf8');
+ try {
+ message = JSON.parse(jsonPayload);
+ } catch (e) {
+ console.error('JSON.parse() failed for: ' + jsonPayload);
+ throw e;
+ }
+ if (DEBUG) console.log('[received]', JSON.stringify(message));
+ return { length: bodyOffset + dataLen, message: message };
+}
+
+function formatWSFrame(message) {
+ var messageBuf = Buffer.from(JSON.stringify(message));
+
+ var wsHeaderBuf = Buffer.allocUnsafe(16);
+ wsHeaderBuf.writeUInt8(0x81, 0);
+ var byte2 = 0x80;
+ var bodyLen = messageBuf.length;
+
+ var maskOffset = 2;
+ if (bodyLen < 126) {
+ byte2 = 0x80 + bodyLen;
+ } else if (bodyLen < 65536) {
+ byte2 = 0xFE;
+ wsHeaderBuf.writeUInt16BE(bodyLen, 2);
+ maskOffset = 4;
+ } else {
+ byte2 = 0xFF;
+ wsHeaderBuf.writeUInt32BE(bodyLen, 2);
+ wsHeaderBuf.writeUInt32BE(0, 6);
+ maskOffset = 10;
+ }
+ wsHeaderBuf.writeUInt8(byte2, 1);
+ wsHeaderBuf.writeUInt32BE(0x01020408, maskOffset);
+
+ for (var _i = 0; _i < messageBuf.length; _i++) {
+ messageBuf[_i] = messageBuf[_i] ^ 1 << _i % 4;
+ }return Buffer.concat([wsHeaderBuf.slice(0, maskOffset + 4), messageBuf]);
+}
+
+var InspectorSession = function () {
+ function InspectorSession(socket, instance) {
+ var _this = this;
+
+ _classCallCheck(this, InspectorSession);
+
+ this._instance = instance;
+ this._socket = socket;
+ this._nextId = 1;
+ this._commandResponsePromises = new Map();
+ this._unprocessedNotifications = [];
+ this._notificationCallback = null;
+ this._scriptsIdsByUrl = new Map();
+
+ var buffer = Buffer.alloc(0);
+ socket.on('data', function (data) {
+ buffer = Buffer.concat([buffer, data]);
+ do {
+ var _parseWSFrame = parseWSFrame(buffer),
+ length = _parseWSFrame.length,
+ message = _parseWSFrame.message,
+ closed = _parseWSFrame.closed;
+
+ if (!length) break;
+
+ if (closed) {
+ socket.write(Buffer.from([0x88, 0x00])); // WS close frame
+ }
+ buffer = buffer.slice(length);
+ if (message) _this._onMessage(message);
+ } while (true);
+ });
+ this._terminationPromise = new Promise(function (resolve) {
+ socket.once('close', resolve);
+ });
+ }
+
+ InspectorSession.prototype.waitForServerDisconnect = function waitForServerDisconnect() {
+ return this._terminationPromise;
+ };
+
+ InspectorSession.prototype.disconnect = function disconnect() {
+ this._socket.destroy();
+ };
+
+ InspectorSession.prototype._onMessage = function _onMessage(message) {
+ if (message.id) {
+ var _commandResponsePromi = this._commandResponsePromises.get(message.id),
+ resolve = _commandResponsePromi.resolve,
+ reject = _commandResponsePromi.reject;
+
+ this._commandResponsePromises.delete(message.id);
+ if (message.result) resolve(message.result);else reject(message.error);
+ } else {
+ if (message.method === 'Debugger.scriptParsed') {
+ var script = message['params'];
+ var scriptId = script['scriptId'];
+ var _url = script['url'];
+ this._scriptsIdsByUrl.set(scriptId, _url);
+ if (_url === _MAINSCRIPT) this.mainScriptId = scriptId;
+ }
+
+ if (this._notificationCallback) {
+ // In case callback needs to install another
+ var callback = this._notificationCallback;
+ this._notificationCallback = null;
+ callback(message);
+ } else {
+ this._unprocessedNotifications.push(message);
+ }
+ }
+ };
+
+ InspectorSession.prototype._sendMessage = function _sendMessage(message) {
+ var _this2 = this;
+
+ var msg = JSON.parse(JSON.stringify(message)); // Clone!
+ msg['id'] = this._nextId++;
+ if (DEBUG) console.log('[sent]', JSON.stringify(msg));
+
+ var responsePromise = new Promise(function (resolve, reject) {
+ _this2._commandResponsePromises.set(msg['id'], { resolve: resolve, reject: reject });
+ });
+
+ return new Promise(function (resolve) {
+ return _this2._socket.write(formatWSFrame(msg), resolve);
+ }).then(function () {
+ return responsePromise;
+ });
+ };
+
+ InspectorSession.prototype.send = function send(commands) {
+ var _this3 = this;
+
+ if (Array.isArray(commands)) {
+ // Multiple commands means the response does not matter. There might even
+ // never be a response.
+ return Promise.all(commands.map(function (command) {
+ return _this3._sendMessage(command);
+ })).then(function () {});
+ } else {
+ return this._sendMessage(commands);
+ }
+ };
+
+ InspectorSession.prototype.waitForNotification = function waitForNotification(methodOrPredicate, description) {
+ var desc = description || methodOrPredicate;
+ var message = 'Timed out waiting for matching notification (' + desc + '))';
+ return common.fires(this._asyncWaitForNotification(methodOrPredicate), message, TIMEOUT);
+ };
+
+ InspectorSession.prototype._asyncWaitForNotification = async function _asyncWaitForNotification(methodOrPredicate) {
+ var _this4 = this;
+
+ function matchMethod(notification) {
+ return notification.method === methodOrPredicate;
+ }
+ var predicate = typeof methodOrPredicate === 'string' ? matchMethod : methodOrPredicate;
+ var notification = null;
+ do {
+ if (this._unprocessedNotifications.length) {
+ notification = this._unprocessedNotifications.shift();
+ } else {
+ notification = await new Promise(function (resolve) {
+ return _this4._notificationCallback = resolve;
+ });
+ }
+ } while (!predicate(notification));
+ return notification;
+ };
+
+ InspectorSession.prototype._isBreakOnLineNotification = function _isBreakOnLineNotification(message, line, url) {
+ if ('Debugger.paused' === message['method']) {
+ var callFrame = message['params']['callFrames'][0];
+ var location = callFrame['location'];
+ assert.strictEqual(url, this._scriptsIdsByUrl.get(location['scriptId']));
+ assert.strictEqual(line, location['lineNumber']);
+ return true;
+ }
+ };
+
+ InspectorSession.prototype.waitForBreakOnLine = function waitForBreakOnLine(line, url) {
+ var _this5 = this;
+
+ return this.waitForNotification(function (notification) {
+ return _this5._isBreakOnLineNotification(notification, line, url);
+ }, 'break on ' + url + ':' + line);
+ };
+
+ InspectorSession.prototype._matchesConsoleOutputNotification = function _matchesConsoleOutputNotification(notification, type, values) {
+ if (!Array.isArray(values)) values = [values];
+ if ('Runtime.consoleAPICalled' === notification['method']) {
+ var params = notification['params'];
+ if (params['type'] === type) {
+ var _i2 = 0;
+ var _iteratorNormalCompletion2 = true;
+ var _didIteratorError2 = false;
+ var _iteratorError2 = undefined;
+
+ try {
+ for (var _iterator2 = params['args'][Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+ var value = _step2.value;
+
+ if (value['value'] !== values[_i2++]) return false;
+ }
+ } catch (err) {
+ _didIteratorError2 = true;
+ _iteratorError2 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion2 && _iterator2.return) {
+ _iterator2.return();
+ }
+ } finally {
+ if (_didIteratorError2) {
+ throw _iteratorError2;
+ }
+ }
+ }
+
+ return _i2 === values.length;
+ }
+ }
+ };
+
+ InspectorSession.prototype.waitForConsoleOutput = function waitForConsoleOutput(type, values) {
+ var _this6 = this;
+
+ var desc = 'Console output matching ' + JSON.stringify(values);
+ return this.waitForNotification(function (notification) {
+ return _this6._matchesConsoleOutputNotification(notification, type, values);
+ }, desc);
+ };
+
+ InspectorSession.prototype.runToCompletion = async function runToCompletion() {
+ console.log('[test]', 'Verify node waits for the frontend to disconnect');
+ await this.send({ 'method': 'Debugger.resume' });
+ await this.waitForNotification(function (notification) {
+ return notification.method === 'Runtime.executionContextDestroyed' && notification.params.executionContextId === 1;
+ });
+ while ((await this._instance.nextStderrString()) !== 'Waiting for the debugger to disconnect...') {}
+ await this.disconnect();
+ };
+
+ return InspectorSession;
+}();
+
+var NodeInstance = function () {
+ function NodeInstance() {
+ var inspectorFlags = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['--inspect-brk=0'];
+
+ var _this7 = this;
+
+ var scriptContents = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
+ var scriptFile = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _MAINSCRIPT;
+
+ _classCallCheck(this, NodeInstance);
+
+ this._portCallback = null;
+ this.portPromise = new Promise(function (resolve) {
+ return _this7._portCallback = resolve;
+ });
+ this._process = spawnChildProcess(inspectorFlags, scriptContents, scriptFile);
+ this._running = true;
+ this._stderrLineCallback = null;
+ this._unprocessedStderrLines = [];
+
+ this._process.stdout.on('data', makeBufferingDataCallback(function (line) {
+ return console.log('[out]', line);
+ }));
+
+ this._process.stderr.on('data', makeBufferingDataCallback(function (message) {
+ return _this7.onStderrLine(message);
+ }));
+
+ this._shutdownPromise = new Promise(function (resolve) {
+ _this7._process.once('exit', function (exitCode, signal) {
+ resolve({ exitCode: exitCode, signal: signal });
+ _this7._running = false;
+ });
+ });
+ }
+
+ NodeInstance.startViaSignal = async function startViaSignal(scriptContents) {
+ var instance = new NodeInstance([], scriptContents + '\nprocess._rawDebug(\'started\');', undefined);
+ var msg = 'Timed out waiting for process to start';
+ while ((await common.fires(instance.nextStderrString(), msg, TIMEOUT)) !== 'started') {}
+ process._debugProcess(instance._process.pid);
+ return instance;
+ };
+
+ NodeInstance.prototype.onStderrLine = function onStderrLine(line) {
+ console.log('[err]', line);
+ if (this._portCallback) {
+ var matches = line.match(/Debugger listening on ws:\/\/.+:(\d+)\/.+/);
+ if (matches) {
+ this._portCallback(matches[1]);
+ this._portCallback = null;
+ }
+ }
+ if (this._stderrLineCallback) {
+ this._stderrLineCallback(line);
+ this._stderrLineCallback = null;
+ } else {
+ this._unprocessedStderrLines.push(line);
+ }
+ };
+
+ NodeInstance.prototype.httpGet = function httpGet(host, path) {
+ console.log('[test]', 'Testing ' + path);
+ return this.portPromise.then(function (port) {
+ return new Promise(function (resolve, reject) {
+ var req = http.get({ host: host, port: port, path: path }, function (res) {
+ var response = '';
+ res.setEncoding('utf8');
+ res.on('data', function (data) {
+ return response += data.toString();
+ }).on('end', function () {
+ resolve(response);
+ });
+ });
+ req.on('error', reject);
+ });
+ }).then(function (response) {
+ try {
+ return JSON.parse(response);
+ } catch (e) {
+ e.body = response;
+ throw e;
+ }
+ });
+ };
+
+ NodeInstance.prototype.wsHandshake = function wsHandshake(devtoolsUrl) {
+ var _this8 = this;
+
+ return this.portPromise.then(function (port) {
+ return new Promise(function (resolve) {
+ http.get({
+ port: port,
+ path: url.parse(devtoolsUrl).path,
+ headers: {
+ 'Connection': 'Upgrade',
+ 'Upgrade': 'websocket',
+ 'Sec-WebSocket-Version': 13,
+ 'Sec-WebSocket-Key': 'key=='
+ }
+ }).on('upgrade', function (message, socket) {
+ resolve(new InspectorSession(socket, _this8));
+ }).on('response', common.mustNotCall('Upgrade was not received'));
+ });
+ });
+ };
+
+ NodeInstance.prototype.connectInspectorSession = async function connectInspectorSession() {
+ console.log('[test]', 'Connecting to a child Node process');
+ var response = await this.httpGet(null, '/json/list');
+ var url = response[0]['webSocketDebuggerUrl'];
+ return this.wsHandshake(url);
+ };
+
+ NodeInstance.prototype.expectShutdown = function expectShutdown() {
+ return this._shutdownPromise;
+ };
+
+ NodeInstance.prototype.nextStderrString = function nextStderrString() {
+ var _this9 = this;
+
+ if (this._unprocessedStderrLines.length) return Promise.resolve(this._unprocessedStderrLines.shift());
+ return new Promise(function (resolve) {
+ return _this9._stderrLineCallback = resolve;
+ });
+ };
+
+ NodeInstance.prototype.kill = function kill() {
+ this._process.kill();
+ };
+
+ return NodeInstance;
+}();
+
+function readMainScriptSource() {
+ return fs.readFileSync(_MAINSCRIPT, 'utf8');
+}
+
+module.exports = {
+ mainScriptPath: _MAINSCRIPT,
+ readMainScriptSource: readMainScriptSource,
+ NodeInstance: NodeInstance
+};
+
+function forEach(xs, f) {
+ for (var i = 0, l = xs.length; i < l; i++) {
+ f(xs[i], i);
+ }
+}
\ No newline at end of file
diff --git a/test/common/wpt.js b/test/common/wpt.js
new file mode 100644
index 0000000..22a5c89
--- /dev/null
+++ b/test/common/wpt.js
@@ -0,0 +1,64 @@
+/**/
+require('babel-polyfill');
+var util = require('util');
+for (var i in util) {
+ exports[i] = util[i];
+} /**/ /**/
+if (!global.setImmediate) {
+ global.setImmediate = function setImmediate(fn) {
+ return setTimeout(fn.bind.apply(fn, arguments), 4);
+ };
+}
+if (!global.clearImmediate) {
+ global.clearImmediate = function clearImmediate(i) {
+ return clearTimeout(i);
+ };
+}
+/**/
+/* eslint-disable required-modules */
+'use strict';
+
+/**/
+var objectKeys = objectKeys || function (obj) {
+ var keys = [];
+ for (var key in obj) {
+ keys.push(key);
+ }return keys;
+};
+/**/
+
+var assert = require('assert');
+
+// https://github.com/w3c/testharness.js/blob/master/testharness.js
+module.exports = {
+ test: function (fn, desc) {
+ try {
+ fn();
+ } catch (err) {
+ console.error('In ' + desc + ':');
+ throw err;
+ }
+ },
+ assert_equals: assert.strictEqual,
+ assert_true: function (value, message) {
+ return assert.strictEqual(value, true, message);
+ },
+ assert_false: function (value, message) {
+ return assert.strictEqual(value, false, message);
+ },
+ assert_throws: function (code, func, desc) {
+ assert.throws(func, function (err) {
+ return typeof err === 'object' && 'name' in err && err.name.startsWith(code.name);
+ }, desc);
+ },
+ assert_array_equals: assert.deepStrictEqual,
+ assert_unreached: function (desc) {
+ assert.fail('Reached unreachable code: ' + desc);
+ }
+};
+
+function forEach(xs, f) {
+ for (var i = 0, l = xs.length; i < l; i++) {
+ f(xs[i], i);
+ }
+}
\ No newline at end of file
diff --git a/test/parallel/test-string-decoder-end.js b/test/parallel/test-string-decoder-end.js
index 2c9b5ac..32abc39 100644
--- a/test/parallel/test-string-decoder-end.js
+++ b/test/parallel/test-string-decoder-end.js
@@ -1,3 +1,24 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
'use strict';
var bufferShim = require('safe-buffer').Buffer;
@@ -24,8 +45,6 @@ for (var i = 1; i <= 16; i++) {
encodings.forEach(testEncoding);
-console.log('ok');
-
function testEncoding(encoding) {
bufs.forEach(function (buf) {
testBuf(encoding, buf);
@@ -33,8 +52,6 @@ function testEncoding(encoding) {
}
function testBuf(encoding, buf) {
- console.error('# %s', encoding, buf);
-
// write one byte at a time.
var s = new SD(encoding);
var res1 = '';
@@ -52,9 +69,6 @@ function testBuf(encoding, buf) {
// .toString() on the buffer
var res3 = buf.toString(encoding);
- console.log('expect=%j', res3);
- console.log('res1=%j', res1);
- console.log('res2=%j', res2);
assert.strictEqual(res1, res3, 'one byte at a time should match toString');
assert.strictEqual(res2, res3, 'all bytes at once should match toString');
}
\ No newline at end of file
diff --git a/test/parallel/test-string-decoder.js b/test/parallel/test-string-decoder.js
index 61d6534..af4f095 100644
--- a/test/parallel/test-string-decoder.js
+++ b/test/parallel/test-string-decoder.js
@@ -1,3 +1,24 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
'use strict';
var bufferShim = require('safe-buffer').Buffer;
@@ -10,8 +31,6 @@ var StringDecoder = require('../../').StringDecoder;
var decoder = new StringDecoder();
assert.strictEqual(decoder.encoding, 'utf8');
-process.stdout.write('scanning ');
-
// UTF-8
test('utf-8', bufferShim.from('$', 'utf-8'), '$');
test('utf-8', bufferShim.from('¢', 'utf-8'), '¢');
@@ -40,22 +59,17 @@ test('utf-8', bufferShim.from('C9B5A941', 'hex'), '\u0275\ufffdA');
test('utf-8', bufferShim.from('E2', 'hex'), '\ufffd');
test('utf-8', bufferShim.from('E241', 'hex'), '\ufffdA');
test('utf-8', bufferShim.from('CCCCB8', 'hex'), '\ufffd\u0338');
-test('utf-8', bufferShim.from('F0B841', 'hex'), '\ufffd\ufffdA');
test('utf-8', bufferShim.from('F1CCB8', 'hex'), '\ufffd\u0338');
test('utf-8', bufferShim.from('F0FB00', 'hex'), '\ufffd\ufffd\0');
-test('utf-8', bufferShim.from('CCE2B8B8', 'hex'), '\ufffd\u2e38');
-test('utf-8', bufferShim.from('E2B8CCB8', 'hex'), '\ufffd\ufffd\u0338');
test('utf-8', bufferShim.from('E2FBCC01', 'hex'), '\ufffd\ufffd\ufffd\u0001');
test('utf-8', bufferShim.from('CCB8CDB9', 'hex'), '\u0338\u0379');
-
+// CESU-8 of U+1D40D
// UCS-2
test('ucs2', bufferShim.from('ababc', 'ucs2'), 'ababc');
// UTF-16LE
test('utf16le', bufferShim.from('3DD84DDC', 'hex'), '\ud83d\udc4d'); // thumbs up
-console.log(' crayon!');
-
// Additional UTF-8 tests
decoder = new StringDecoder('utf8');
assert.strictEqual(decoder.write(bufferShim.from('E1', 'hex')), '');
@@ -63,7 +77,7 @@ assert.strictEqual(decoder.end(), '\ufffd');
decoder = new StringDecoder('utf8');
assert.strictEqual(decoder.write(bufferShim.from('E18B', 'hex')), '');
-assert.strictEqual(decoder.end(), '\ufffd\ufffd');
+assert.strictEqual(decoder.end(), '\ufffd');
decoder = new StringDecoder('utf8');
assert.strictEqual(decoder.write(bufferShim.from('\ufffd')), '\ufffd');
@@ -122,6 +136,7 @@ function test(encoding, input, expected, singleSequence) {
} else {
sequences = [singleSequence];
}
+ var hexNumberRE = /.{2}/g;
sequences.forEach(function (sequence) {
var decoder = new StringDecoder(encoding);
var output = '';
@@ -129,9 +144,8 @@ function test(encoding, input, expected, singleSequence) {
output += decoder.write(input.slice(write[0], write[1]));
});
output += decoder.end();
- process.stdout.write('.');
if (output !== expected) {
- var message = 'Expected "' + unicodeEscape(expected) + '", ' + 'but got "' + unicodeEscape(output) + '"\n' + 'input: ' + input.toString('hex').match(/.{2}/g) + '\n' + 'Write sequence: ' + JSON.stringify(sequence) + '\n' + 'Full Decoder State: ' + inspect(decoder);
+ var message = 'Expected "' + unicodeEscape(expected) + '", ' + ('but got "' + unicodeEscape(output) + '"\n') + ('input: ' + input.toString('hex').match(hexNumberRE) + '\n') + ('Write sequence: ' + JSON.stringify(sequence) + '\n') + ('Full Decoder State: ' + inspect(decoder));
assert.fail(output, expected, message);
}
});