From 92d6f826b572d3341b520a50b3e1ba4d1498526d Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Wed, 21 Mar 2018 01:19:05 +0800 Subject: [PATCH 1/4] test: add info option to common.expectsError --- test/common/README.md | 2 ++ test/common/index.js | 3 +++ 2 files changed, 5 insertions(+) diff --git a/test/common/README.md b/test/common/README.md index 765ebe01231a72..981e27a26b24c5 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -86,6 +86,8 @@ Indicates if there is more than 1gb of total memory. regular expression must match the `message` property of the expected error. * `name` [<string>] expected error must have this value for its `name` property. + * `info` <Object> expected error must have the same `info` property + that is deeply equal to this value. * `generatedMessage` [<string>] (`AssertionError` only) expected error must have this value for its `generatedMessage` property. diff --git a/test/common/index.js b/test/common/index.js index 4c4f0342f2f6ca..de92596045b748 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -704,6 +704,9 @@ exports.expectsError = function expectsError(fn, settings, exact) { } assert.strictEqual(typeName, type.name); } + if ('info' in settings) { + assert.deepStrictEqual(error.info, settings.info); + } if ('message' in settings) { const message = settings.message; if (typeof message === 'string') { From a4970e16534a69a3cca55fb55fd22a4e9c090268 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Wed, 21 Mar 2018 00:46:30 +0800 Subject: [PATCH 2/4] errors: improve SystemError messages This commit improves the SystemError messages by allowing user to combine a custom message and the libuv error message. Also since we now prefer use subclasses to construct the errors instead of using `new errors.SystemError()` directly, this removes the behavior of assigning a default error code `ERR_SYSTEM_ERROR` to SystemError and requires the user to directly use the `ERR_SYSTEM_ERROR` class to construct errors instead. Also merges `makeNodeError` into the SystemError class definition since that's the only place the function gets used and it seems unnecessary to introduce another level of inheritance. SystemError now directly inherits from Error instead of an intermmediate Error class that inherits from Error. Class hierarchy before this patch: ERR_SOCKET_BUFFER_SIZE -> Error (use message formatted by SystemError) ERR_SYSTEM_ERROR -> NodeError (temp) -> Error After: ERR_SOCKET_BUFFER_SIZE -> SystemError -> Error ERR_TTY_INIT_FAILED -> SystemError -> Error ERR_SYSTEM_ERROR -> SystemError -> Error Error messages before this patch: ``` const dgram = require('dgram'); const socket = dgram.createSocket('udp4'); socket.setRecvBufferSize(8192); // Error [ERR_SOCKET_BUFFER_SIZE]: Could not get or set buffer // size: Error [ERR_SYSTEM_ERROR]: bad file descriptor: // EBADF [uv_recv_buffer_size] // at bufferSize (dgram.js:191:11) // at Socket.setRecvBufferSize (dgram.js:689:3) const tty = require('tty'); new tty.WriteStream(1 << 30); // Error [ERR_SYSTEM_ERROR]: invalid argument: EINVAL [uv_tty_init] // at new WriteStream (tty.js:84:11) ``` After: ``` const dgram = require('dgram'); const socket = dgram.createSocket('udp4'); socket.setRecvBufferSize(8192); // SystemError [ERR_SOCKET_BUFFER_SIZE]: Could not get or set buffer // size: uv_recv_buffer_size returns EBADF (bad file descriptor) // at bufferSize (dgram.js:191:11) // at Socket.setRecvBufferSize (dgram.js:689:3) const tty = require('tty'); new tty.WriteStream(1 << 30); // SystemError [ERR_TTY_INIT_FAILED]: TTY initialization failed: // uv_tty_init returns EINVAL (invalid argument) // at new WriteStream (tty.js:84:11) ``` --- doc/api/errors.md | 5 + lib/dgram.js | 2 +- lib/internal/errors.js | 231 +++++++++--------- lib/os.js | 4 +- lib/tty.js | 6 +- .../parallel/test-dgram-socket-buffer-size.js | 88 +++++-- test/parallel/test-errors-systemerror.js | 160 ++++-------- test/parallel/test-ttywrap-invalid-fd.js | 24 +- 8 files changed, 259 insertions(+), 261 deletions(-) diff --git a/doc/api/errors.md b/doc/api/errors.md index 62a62d76656223..03106394747263 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -1526,6 +1526,11 @@ A Transform stream finished while it was still transforming. A Transform stream finished with data still in the write buffer. + +### ERR_TTY_INIT_FAILED + +The initialization of a TTY failed due to a system error. + ### ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET diff --git a/lib/dgram.js b/lib/dgram.js index fcf9f00a105101..0a72834873e8bd 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -188,7 +188,7 @@ function bufferSize(self, size, buffer) { const ctx = {}; const ret = self._handle.bufferSize(size, buffer, ctx); if (ret === undefined) { - throw new ERR_SOCKET_BUFFER_SIZE(new errors.SystemError(ctx)); + throw new ERR_SOCKET_BUFFER_SIZE(ctx); } return ret; } diff --git a/lib/internal/errors.js b/lib/internal/errors.js index f8073d15fe8d49..70e2d63317b8d5 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -47,42 +47,112 @@ function inspectValue(val) { ).split('\n'); } -function makeNodeError(Base) { - return class NodeError extends Base { - constructor(key, ...args) { - super(message(key, args)); - defineProperty(this, kCode, { - configurable: true, - enumerable: false, - value: key, - writable: true - }); - } +function sysErrorMessage(prefix, ctx) { + let message = `${prefix}: ${ctx.syscall} returns ` + + `${ctx.code} (${ctx.message})`; + if (ctx.path !== undefined) + message += ` ${ctx.path}`; + if (ctx.dest !== undefined) + message += ` => ${ctx.dest}`; + return message; +} - get name() { - return `${super.name} [${this[kCode]}]`; - } +// A specialized Error that includes an additional info property with +// additional information about the error condition. +// It has the properties present in a UVException but with a custom error +// message followed by the uv error code and uv error message. +// It also has its own error code with the original uv error context put into +// `err.info`. +// The context passed into this error must have .code, .syscall and .message, +// and may have .path and .dest. +class SystemError extends Error { + constructor(key, context = {}) { + context = context || {}; + super(sysErrorMessage(message(key), context)); + Object.defineProperty(this, kInfo, { + configurable: false, + enumerable: false, + value: context + }); + Object.defineProperty(this, kCode, { + configurable: true, + enumerable: false, + value: key, + writable: true + }); + } - set name(value) { - defineProperty(this, 'name', { - configurable: true, - enumerable: true, - value, - writable: true - }); - } + get name() { + return `SystemError [${this[kCode]}]`; + } - get code() { - return this[kCode]; - } + set name(value) { + defineProperty(this, 'name', { + configurable: true, + enumerable: true, + value, + writable: true + }); + } - set code(value) { - defineProperty(this, 'code', { - configurable: true, - enumerable: true, - value, - writable: true - }); + get code() { + return this[kCode]; + } + + set code(value) { + defineProperty(this, 'code', { + configurable: true, + enumerable: true, + value, + writable: true + }); + } + + get info() { + return this[kInfo]; + } + + get errno() { + return this[kInfo].errno; + } + + set errno(val) { + this[kInfo].errno = val; + } + + get syscall() { + return this[kInfo].syscall; + } + + set syscall(val) { + this[kInfo].syscall = val; + } + + get path() { + return this[kInfo].path !== undefined ? + this[kInfo].path.toString() : undefined; + } + + set path(val) { + this[kInfo].path = val ? + lazyBuffer().from(val.toString()) : undefined; + } + + get dest() { + return this[kInfo].path !== undefined ? + this[kInfo].dest.toString() : undefined; + } + + set dest(val) { + this[kInfo].dest = val ? + lazyBuffer().from(val.toString()) : undefined; + } +} + +function makeSystemErrorWithCode(key) { + return class NodeError extends SystemError { + constructor(...args) { + super(key, ...args); } }; } @@ -124,8 +194,15 @@ function makeNodeErrorWithCode(Base, key) { // Utility function for registering the error codes. Only used here. Exported // *only* to allow for testing. function E(sym, val, def, ...otherClasses) { + // Special case for SystemError that formats the error message differently + // The SystemErrors only have SystemError as their base classes. messages.set(sym, val); - def = makeNodeErrorWithCode(def, sym); + if (def === SystemError) { + def = makeSystemErrorWithCode(sym); + } else { + def = makeNodeErrorWithCode(def, sym); + } + if (otherClasses.length !== 0) { otherClasses.forEach((clazz) => { def[clazz.name] = makeNodeErrorWithCode(clazz, sym); @@ -140,70 +217,6 @@ function lazyBuffer() { return buffer; } -// A specialized Error that includes an additional info property with -// additional information about the error condition. The code key will -// be extracted from the context object or the ERR_SYSTEM_ERROR default -// will be used. -class SystemError extends makeNodeError(Error) { - constructor(context) { - context = context || {}; - let code = 'ERR_SYSTEM_ERROR'; - if (messages.has(context.code)) - code = context.code; - super(code, - context.code, - context.syscall, - context.path, - context.dest, - context.message); - Object.defineProperty(this, kInfo, { - configurable: false, - enumerable: false, - value: context - }); - } - - get info() { - return this[kInfo]; - } - - get errno() { - return this[kInfo].errno; - } - - set errno(val) { - this[kInfo].errno = val; - } - - get syscall() { - return this[kInfo].syscall; - } - - set syscall(val) { - this[kInfo].syscall = val; - } - - get path() { - return this[kInfo].path !== undefined ? - this[kInfo].path.toString() : undefined; - } - - set path(val) { - this[kInfo].path = val ? - lazyBuffer().from(val.toString()) : undefined; - } - - get dest() { - return this[kInfo].path !== undefined ? - this[kInfo].dest.toString() : undefined; - } - - set dest(val) { - this[kInfo].dest = val ? - lazyBuffer().from(val.toString()) : undefined; - } -} - function createErrDiff(actual, expected, operator) { var other = ''; var res = ''; @@ -872,7 +885,9 @@ E('ERR_SOCKET_BAD_PORT', 'Port should be > 0 and < 65536. Received %s.', RangeError); E('ERR_SOCKET_BAD_TYPE', 'Bad socket type specified. Valid types are: udp4, udp6', TypeError); -E('ERR_SOCKET_BUFFER_SIZE', 'Could not get or set buffer size: %s', Error); +E('ERR_SOCKET_BUFFER_SIZE', + 'Could not get or set buffer size', + SystemError); E('ERR_SOCKET_CANNOT_SEND', 'Unable to send data', Error); E('ERR_SOCKET_CLOSED', 'Socket is closed', Error); E('ERR_SOCKET_DGRAM_NOT_RUNNING', 'Not running', Error); @@ -886,6 +901,7 @@ E('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event', Error); E('ERR_STREAM_WRAP', 'Stream has StringDecoder set or is in objectMode', Error); E('ERR_STREAM_WRITE_AFTER_END', 'write after end', Error); +E('ERR_SYSTEM_ERROR', 'A system error occurred', SystemError); E('ERR_TLS_CERT_ALTNAME_INVALID', 'Hostname/IP does not match certificate\'s altnames: %s', Error); E('ERR_TLS_DH_PARAM_SIZE', 'DH parameter size %s is less than 2048', Error); @@ -905,6 +921,7 @@ E('ERR_TRANSFORM_ALREADY_TRANSFORMING', // This should probably be a `RangeError`. E('ERR_TRANSFORM_WITH_LENGTH_0', 'Calling transform done when writableState.length != 0', Error); +E('ERR_TTY_INIT_FAILED', 'TTY initialization failed', SystemError); E('ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET', '`process.setupUncaughtExceptionCapture()` was called while a capture ' + 'callback was already active', @@ -945,24 +962,6 @@ E('ERR_VM_MODULE_NOT_MODULE', E('ERR_VM_MODULE_STATUS', 'Module status %s', Error); E('ERR_ZLIB_INITIALIZATION_FAILED', 'Initialization failed', Error); -function sysError(code, syscall, path, dest, - message = 'A system error occurred') { - if (code !== undefined) - message += `: ${code}`; - if (syscall !== undefined) { - if (code === undefined) - message += ':'; - message += ` [${syscall}]`; - } - if (path !== undefined) { - message += `: ${path}`; - if (dest !== undefined) - message += ` => ${dest}`; - } - return message; -} -messages.set('ERR_SYSTEM_ERROR', sysError); - function invalidArgType(name, expected, actual) { internalAssert(typeof name === 'string'); internalAssert(arguments.length === 3); diff --git a/lib/os.js b/lib/os.js index eb13139dba9a9c..5c83dbfab7b6e3 100644 --- a/lib/os.js +++ b/lib/os.js @@ -27,7 +27,7 @@ const { deprecate } = require('internal/util'); const { getCIDRSuffix } = require('internal/os'); const isWindows = process.platform === 'win32'; -const errors = require('internal/errors'); +const { ERR_SYSTEM_ERROR } = require('internal/errors'); const { getCPUs, @@ -49,7 +49,7 @@ function getCheckedFunction(fn) { const ctx = {}; const ret = fn(...args, ctx); if (ret === undefined) { - const err = new errors.SystemError(ctx); + const err = new ERR_SYSTEM_ERROR(ctx); Error.captureStackTrace(err, checkError); throw err; } diff --git a/lib/tty.js b/lib/tty.js index 51ec1cf89810bd..8a8dd736be276d 100644 --- a/lib/tty.js +++ b/lib/tty.js @@ -25,7 +25,7 @@ const { inherits, _extend } = require('util'); const net = require('net'); const { TTY, isTTY } = process.binding('tty_wrap'); const errors = require('internal/errors'); -const { ERR_INVALID_FD } = errors.codes; +const { ERR_INVALID_FD, ERR_TTY_INIT_FAILED } = errors.codes; const readline = require('readline'); const { release } = require('os'); @@ -49,7 +49,7 @@ function ReadStream(fd, options) { const ctx = {}; const tty = new TTY(fd, true, ctx); if (ctx.code !== undefined) { - throw new errors.SystemError(ctx); + throw new ERR_TTY_INIT_FAILED(ctx); } options = _extend({ @@ -81,7 +81,7 @@ function WriteStream(fd) { const ctx = {}; const tty = new TTY(fd, false, ctx); if (ctx.code !== undefined) { - throw new errors.SystemError(ctx); + throw new ERR_TTY_INIT_FAILED(ctx); } net.Socket.call(this, { diff --git a/test/parallel/test-dgram-socket-buffer-size.js b/test/parallel/test-dgram-socket-buffer-size.js index 1fe72690d23aa9..fce03dbd9ae93f 100644 --- a/test/parallel/test-dgram-socket-buffer-size.js +++ b/test/parallel/test-dgram-socket-buffer-size.js @@ -1,33 +1,61 @@ 'use strict'; +// Flags: --expose-internals const common = require('../common'); const assert = require('assert'); const dgram = require('dgram'); +const { SystemError } = require('internal/errors'); +const uv = process.binding('uv'); + +function getExpectedError(type) { + const code = common.isWindows ? 'ENOTSOCK' : 'EBADF'; + const message = common.isWindows ? + 'socket operation on non-socket' : 'bad file descriptor'; + const errno = common.isWindows ? uv.UV_ENOTSOCK : uv.UV_EBADF; + const syscall = `uv_${type}_buffer_size`; + const suffix = common.isWindows ? + 'ENOTSOCK (socket operation on non-socket)' : 'EBADF (bad file descriptor)'; + const error = { + code: 'ERR_SOCKET_BUFFER_SIZE', + type: SystemError, + message: `Could not get or set buffer size: ${syscall} returns ${suffix}`, + info: { + code, + message, + errno, + syscall + } + }; + return error; +} { // Should throw error if the socket is never bound. - const errorObj = { - code: 'ERR_SOCKET_BUFFER_SIZE', - type: Error, - message: /^Could not get or set buffer size:.*$/ - }; + const errorObj = getExpectedError('send'); const socket = dgram.createSocket('udp4'); common.expectsError(() => { - socket.setRecvBufferSize(8192); + socket.setSendBufferSize(8192); }, errorObj); common.expectsError(() => { - socket.setSendBufferSize(8192); + socket.getSendBufferSize(); }, errorObj); +} + +{ + const socket = dgram.createSocket('udp4'); + + // Should throw error if the socket is never bound. + const errorObj = getExpectedError('recv'); common.expectsError(() => { - socket.getRecvBufferSize(); + socket.setRecvBufferSize(8192); }, errorObj); common.expectsError(() => { - socket.getSendBufferSize(); + socket.getRecvBufferSize(); }, errorObj); } @@ -73,22 +101,48 @@ const dgram = require('dgram'); })); } -function checkBufferSizeError(type, size) { +{ + const info = { + code: 'EINVAL', + message: 'invalid argument', + errno: uv.UV_EINVAL, + syscall: 'uv_recv_buffer_size' + }; const errorObj = { code: 'ERR_SOCKET_BUFFER_SIZE', - type: Error, - message: /^Could not get or set buffer size:.*$/ + type: SystemError, + message: 'Could not get or set buffer size: uv_recv_buffer_size ' + + 'returns EINVAL (invalid argument)', + info }; - const functionName = `set${type.charAt(0).toUpperCase()}${type.slice(1)}` + - 'BufferSize'; const socket = dgram.createSocket('udp4'); socket.bind(common.mustCall(() => { common.expectsError(() => { - socket[functionName](size); + socket.setRecvBufferSize(2147483648); }, errorObj); socket.close(); })); } -checkBufferSizeError('recv', 2147483648); -checkBufferSizeError('send', 2147483648); +{ + const info = { + code: 'EINVAL', + message: 'invalid argument', + errno: uv.UV_EINVAL, + syscall: 'uv_send_buffer_size' + }; + const errorObj = { + code: 'ERR_SOCKET_BUFFER_SIZE', + type: SystemError, + message: 'Could not get or set buffer size: uv_send_buffer_size ' + + 'returns EINVAL (invalid argument)', + info + }; + const socket = dgram.createSocket('udp4'); + socket.bind(common.mustCall(() => { + common.expectsError(() => { + socket.setSendBufferSize(2147483648); + }, errorObj); + socket.close(); + })); +} diff --git a/test/parallel/test-errors-systemerror.js b/test/parallel/test-errors-systemerror.js index 45ac7341752512..7f46ddf3017fde 100644 --- a/test/parallel/test-errors-systemerror.js +++ b/test/parallel/test-errors-systemerror.js @@ -4,149 +4,79 @@ const common = require('../common'); const assert = require('assert'); const errors = require('internal/errors'); +const { AssertionError } = require('assert'); -common.expectsError( - () => { throw new errors.SystemError(); }, - { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred' - } -); - -common.expectsError( - () => { throw new errors.SystemError({}); }, - { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred' - } -); +const { E, SystemError } = errors; common.expectsError( - () => { throw new errors.SystemError(null); }, + () => { throw new errors.SystemError(); }, { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred' + code: 'ERR_ASSERTION', + type: AssertionError, + message: 'An invalid error message key was used: undefined.' } ); -common.expectsError( - () => { throw new errors.SystemError({ code: 'ERR' }); }, - { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred: ERR' - } -); +E('ERR_TEST', 'custom message', SystemError); +const { ERR_TEST } = errors.codes; { const ctx = { - code: 'ERR', - syscall: 'foo' + code: 'ETEST', + message: 'code message', + syscall: 'syscall_test', + path: '/str', + dest: '/str2' }; - common.expectsError( - () => { throw new errors.SystemError(ctx); }, - { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred: ERR [foo]' - } - ); -} -{ - const ctx = { - code: 'ERR', - syscall: 'foo', - path: Buffer.from('a') - }; common.expectsError( - () => { throw new errors.SystemError(ctx); }, + () => { throw new ERR_TEST(ctx); }, { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred: ERR [foo]: a' + code: 'ERR_TEST', + type: SystemError, + message: 'custom message: syscall_test returns ETEST (code message)' + + ' /str => /str2', + info: ctx } ); } { const ctx = { - code: 'ERR', - syscall: 'foo', - path: Buffer.from('a'), - dest: Buffer.from('b') - }; - common.expectsError( - () => { throw new errors.SystemError(ctx); }, - { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred: ERR [foo]: a => b' - } - ); -} - -{ - const ctx = { - syscall: 'foo', - path: Buffer.from('a'), - dest: Buffer.from('b') - }; - common.expectsError( - () => { throw new errors.SystemError(ctx); }, - { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred: [foo]: a => b' - } - ); -} - -{ - const ctx = { - path: Buffer.from('a'), - dest: Buffer.from('b') - }; - common.expectsError( - () => { throw new errors.SystemError(ctx); }, - { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred: a => b' - } - ); -} - -{ - const ctx = { - code: 'ERR', - message: 'something happened', - syscall: 'foo', - path: Buffer.from('a'), - dest: Buffer.from('b') + code: 'ETEST', + message: 'code message', + syscall: 'syscall_test', + path: Buffer.from('/buf'), + dest: '/str2' }; common.expectsError( - () => { throw new errors.SystemError(ctx); }, + () => { throw new ERR_TEST(ctx); }, { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'something happened: ERR [foo]: a => b' + code: 'ERR_TEST', + type: SystemError, + message: 'custom message: syscall_test returns ETEST (code message)' + + ' /buf => /str2', + info: ctx } ); } { const ctx = { - code: 'ERR_ASSERTION' + code: 'ETEST', + message: 'code message', + syscall: 'syscall_test', + path: Buffer.from('/buf'), + dest: Buffer.from('/buf2') }; common.expectsError( - () => { throw new errors.SystemError(ctx); }, + () => { throw new ERR_TEST(ctx); }, { - code: 'ERR_ASSERTION', - type: errors.SystemError + code: 'ERR_TEST', + type: SystemError, + message: 'custom message: syscall_test returns ETEST (code message)' + + ' /buf => /buf2', + info: ctx } ); } @@ -156,20 +86,20 @@ common.expectsError( code: 'ERR', errno: 123, message: 'something happened', - syscall: 'foo', + syscall: 'syscall_test', path: Buffer.from('a'), dest: Buffer.from('b') }; - const err = new errors.SystemError(ctx); + const err = new ERR_TEST(ctx); assert.strictEqual(err.info, ctx); - assert.strictEqual(err.code, 'ERR_SYSTEM_ERROR'); + assert.strictEqual(err.code, 'ERR_TEST'); err.code = 'test'; assert.strictEqual(err.code, 'test'); // Test legacy properties. These shouldn't be used anymore // but let us make sure they still work assert.strictEqual(err.errno, 123); - assert.strictEqual(err.syscall, 'foo'); + assert.strictEqual(err.syscall, 'syscall_test'); assert.strictEqual(err.path, 'a'); assert.strictEqual(err.dest, 'b'); diff --git a/test/parallel/test-ttywrap-invalid-fd.js b/test/parallel/test-ttywrap-invalid-fd.js index adf88cbde659ce..43d3705154f785 100644 --- a/test/parallel/test-ttywrap-invalid-fd.js +++ b/test/parallel/test-ttywrap-invalid-fd.js @@ -4,6 +4,7 @@ const common = require('../common'); const tty = require('tty'); const { SystemError } = require('internal/errors'); +const uv = process.binding('uv'); common.expectsError( () => new tty.WriteStream(-1), @@ -15,9 +16,16 @@ common.expectsError( ); { - const message = common.isWindows ? - 'bad file descriptor: EBADF [uv_tty_init]' : - 'invalid argument: EINVAL [uv_tty_init]'; + const info = { + code: common.isWindows ? 'EBADF' : 'EINVAL', + message: common.isWindows ? 'bad file descriptor' : 'invalid argument', + errno: common.isWindows ? uv.UV_EBADF : uv.UV_EINVAL, + syscall: 'uv_tty_init' + }; + + const suffix = common.isWindows ? + 'EBADF (bad file descriptor)' : 'EINVAL (invalid argument)'; + const message = `TTY initialization failed: uv_tty_init returns ${suffix}`; common.expectsError( () => { @@ -25,9 +33,10 @@ common.expectsError( new tty.WriteStream(fd); }); }, { - code: 'ERR_SYSTEM_ERROR', + code: 'ERR_TTY_INIT_FAILED', type: SystemError, - message + message, + info } ); @@ -37,9 +46,10 @@ common.expectsError( new tty.ReadStream(fd); }); }, { - code: 'ERR_SYSTEM_ERROR', + code: 'ERR_TTY_INIT_FAILED', type: SystemError, - message + message, + info }); } From 3566fadcbd46542ef10a8a852f56803b6b6290d9 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Wed, 4 Apr 2018 13:54:10 +0800 Subject: [PATCH 3/4] squash! errors: improve SystemError messages returns -> returned --- lib/internal/errors.js | 2 +- test/parallel/test-dgram-socket-buffer-size.js | 6 +++--- test/parallel/test-errors-systemerror.js | 6 +++--- test/parallel/test-ttywrap-invalid-fd.js | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 70e2d63317b8d5..17b6f966d42357 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -48,7 +48,7 @@ function inspectValue(val) { } function sysErrorMessage(prefix, ctx) { - let message = `${prefix}: ${ctx.syscall} returns ` + + let message = `${prefix}: ${ctx.syscall} returned ` + `${ctx.code} (${ctx.message})`; if (ctx.path !== undefined) message += ` ${ctx.path}`; diff --git a/test/parallel/test-dgram-socket-buffer-size.js b/test/parallel/test-dgram-socket-buffer-size.js index fce03dbd9ae93f..834ca30c57d926 100644 --- a/test/parallel/test-dgram-socket-buffer-size.js +++ b/test/parallel/test-dgram-socket-buffer-size.js @@ -18,7 +18,7 @@ function getExpectedError(type) { const error = { code: 'ERR_SOCKET_BUFFER_SIZE', type: SystemError, - message: `Could not get or set buffer size: ${syscall} returns ${suffix}`, + message: `Could not get or set buffer size: ${syscall} returned ${suffix}`, info: { code, message, @@ -112,7 +112,7 @@ function getExpectedError(type) { code: 'ERR_SOCKET_BUFFER_SIZE', type: SystemError, message: 'Could not get or set buffer size: uv_recv_buffer_size ' + - 'returns EINVAL (invalid argument)', + 'returned EINVAL (invalid argument)', info }; const socket = dgram.createSocket('udp4'); @@ -135,7 +135,7 @@ function getExpectedError(type) { code: 'ERR_SOCKET_BUFFER_SIZE', type: SystemError, message: 'Could not get or set buffer size: uv_send_buffer_size ' + - 'returns EINVAL (invalid argument)', + 'returned EINVAL (invalid argument)', info }; const socket = dgram.createSocket('udp4'); diff --git a/test/parallel/test-errors-systemerror.js b/test/parallel/test-errors-systemerror.js index 7f46ddf3017fde..285c89b5d25c2a 100644 --- a/test/parallel/test-errors-systemerror.js +++ b/test/parallel/test-errors-systemerror.js @@ -34,7 +34,7 @@ const { ERR_TEST } = errors.codes; { code: 'ERR_TEST', type: SystemError, - message: 'custom message: syscall_test returns ETEST (code message)' + + message: 'custom message: syscall_test returned ETEST (code message)' + ' /str => /str2', info: ctx } @@ -54,7 +54,7 @@ const { ERR_TEST } = errors.codes; { code: 'ERR_TEST', type: SystemError, - message: 'custom message: syscall_test returns ETEST (code message)' + + message: 'custom message: syscall_test returned ETEST (code message)' + ' /buf => /str2', info: ctx } @@ -74,7 +74,7 @@ const { ERR_TEST } = errors.codes; { code: 'ERR_TEST', type: SystemError, - message: 'custom message: syscall_test returns ETEST (code message)' + + message: 'custom message: syscall_test returned ETEST (code message)' + ' /buf => /buf2', info: ctx } diff --git a/test/parallel/test-ttywrap-invalid-fd.js b/test/parallel/test-ttywrap-invalid-fd.js index 43d3705154f785..c360489cb33529 100644 --- a/test/parallel/test-ttywrap-invalid-fd.js +++ b/test/parallel/test-ttywrap-invalid-fd.js @@ -25,7 +25,7 @@ common.expectsError( const suffix = common.isWindows ? 'EBADF (bad file descriptor)' : 'EINVAL (invalid argument)'; - const message = `TTY initialization failed: uv_tty_init returns ${suffix}`; + const message = `TTY initialization failed: uv_tty_init returned ${suffix}`; common.expectsError( () => { From 0c47df25543adbaa4d54aa6e34e2578f56e39717 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Wed, 4 Apr 2018 16:54:13 +0800 Subject: [PATCH 4/4] squash! test: add info option to common.expectsError --- test/common/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/common/index.js b/test/common/index.js index de92596045b748..ba53065ef01d01 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -720,7 +720,7 @@ exports.expectsError = function expectsError(fn, settings, exact) { // Check all error properties. const keys = Object.keys(settings); for (const key of keys) { - if (key === 'message' || key === 'type') + if (key === 'message' || key === 'type' || key === 'info') continue; const actual = error[key]; const expected = settings[key];