nodejs/test/parallel/test-errors-systemerror.js
Joyee Cheung 7d06761f83
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 returned 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 returned EINVAL (invalid argument)
//     at new WriteStream (tty.js:84:11)
```

PR-URL: https://github.com/nodejs/node/pull/19514
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2018-04-05 04:46:26 +08:00

118 lines
2.6 KiB
JavaScript

// Flags: --expose-internals
'use strict';
const common = require('../common');
const assert = require('assert');
const errors = require('internal/errors');
const { AssertionError } = require('assert');
const { E, SystemError } = errors;
common.expectsError(
() => { throw new errors.SystemError(); },
{
code: 'ERR_ASSERTION',
type: AssertionError,
message: 'An invalid error message key was used: undefined.'
}
);
E('ERR_TEST', 'custom message', SystemError);
const { ERR_TEST } = errors.codes;
{
const ctx = {
code: 'ETEST',
message: 'code message',
syscall: 'syscall_test',
path: '/str',
dest: '/str2'
};
common.expectsError(
() => { throw new ERR_TEST(ctx); },
{
code: 'ERR_TEST',
type: SystemError,
message: 'custom message: syscall_test returned ETEST (code message)' +
' /str => /str2',
info: ctx
}
);
}
{
const ctx = {
code: 'ETEST',
message: 'code message',
syscall: 'syscall_test',
path: Buffer.from('/buf'),
dest: '/str2'
};
common.expectsError(
() => { throw new ERR_TEST(ctx); },
{
code: 'ERR_TEST',
type: SystemError,
message: 'custom message: syscall_test returned ETEST (code message)' +
' /buf => /str2',
info: ctx
}
);
}
{
const ctx = {
code: 'ETEST',
message: 'code message',
syscall: 'syscall_test',
path: Buffer.from('/buf'),
dest: Buffer.from('/buf2')
};
common.expectsError(
() => { throw new ERR_TEST(ctx); },
{
code: 'ERR_TEST',
type: SystemError,
message: 'custom message: syscall_test returned ETEST (code message)' +
' /buf => /buf2',
info: ctx
}
);
}
{
const ctx = {
code: 'ERR',
errno: 123,
message: 'something happened',
syscall: 'syscall_test',
path: Buffer.from('a'),
dest: Buffer.from('b')
};
const err = new ERR_TEST(ctx);
assert.strictEqual(err.info, ctx);
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, 'syscall_test');
assert.strictEqual(err.path, 'a');
assert.strictEqual(err.dest, 'b');
// Make sure it's mutable
err.code = 'test';
err.errno = 321;
err.syscall = 'test';
err.path = 'path';
err.dest = 'path';
assert.strictEqual(err.errno, 321);
assert.strictEqual(err.syscall, 'test');
assert.strictEqual(err.path, 'path');
assert.strictEqual(err.dest, 'path');
}