Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

errors,crypto: use internal/errors.js #14724

Closed
wants to merge 5 commits into from
Closed

Conversation

rumkin
Copy link
Contributor

@rumkin rumkin commented Aug 10, 2017

Change crypto.js to use internal/errors.js module.

See #11273 for more info.

cc @jasnell

Checklist

  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • documentation is changed or added
  • commit message follows commit guidelines

Affected core subsystem(s)

errors, crypto

@nodejs-github-bot nodejs-github-bot added crypto Issues and PRs related to the crypto subsystem. errors Issues and PRs related to JavaScript errors originated in Node.js core. labels Aug 10, 2017
@refack refack self-assigned this Aug 10, 2017
@refack
Copy link
Contributor

refack commented Aug 10, 2017

@rumkin thank you for this contribution.
I've run a quick CI to check if tests need to be updated with the new errors - https://ci.nodejs.org/job/node-test-commit-linuxone/7864/

not ok 282 parallel/test-crypto-dh
  ---
  duration_ms: 0.176
  severity: fail
  stack: |-
    assert.js:632
          throw actual;
          ^
    
    TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of type number, string, Buffer, TypedArray, or DataView
        at new DiffieHellman (crypto.js:421:11)
        at Object.DiffieHellman (crypto.js:416:12)
        at assert.throws (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/parallel/test-crypto-dh.js:29:10)
        at tryBlock (assert.js:602:5)
        at innerThrows (assert.js:621:18)
        at Function.throws (assert.js:648:3)
        at Object.<anonymous> (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/parallel/test-crypto-dh.js:28:8)
        at Module._compile (module.js:573:30)
        at Object.Module._extensions..js (module.js:584:10)
        at Module.load (module.js:507:32)
  ...
not ok 290 parallel/test-crypto-engine
  ---
  duration_ms: 0.92
  severity: fail
  stack: |-
    assert.js:632
          throw actual;
          ^
    
    TypeError [ERR_INVALID_ARG_TYPE]: The "id" argument must be of type string
        at Object.setEngine (crypto.js:688:11)
        at /data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/parallel/test-crypto-engine.js:11:10
        at tryBlock (assert.js:602:5)
        at innerThrows (assert.js:621:18)
        at Function.throws (assert.js:648:3)
        at Object.<anonymous> (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/parallel/test-crypto-engine.js:10:8)
        at Module._compile (module.js:573:30)
        at Object.Module._extensions..js (module.js:584:10)
        at Module.load (module.js:507:32)
        at tryModuleLoad (module.js:470:12)
  ...
not ok 299 parallel/test-crypto-pbkdf2
  ---
  duration_ms: 0.138
  severity: fail
  stack: |-
    assert.js:632
          throw actual;
          ^
    
    Error [ERR_CRYPTO_MISSING_PBKDF2_CALLBACK]: No callback provided to pbkdf2
        at Object.exports.pbkdf2 (crypto.js:622:11)
        at /data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/parallel/test-crypto-pbkdf2.js:59:10
        at tryBlock (assert.js:602:5)
        at innerThrows (assert.js:621:18)
        at Function.throws (assert.js:648:3)
        at Object.<anonymous> (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/parallel/test-crypto-pbkdf2.js:58:8)
        at Module._compile (module.js:573:30)
        at Object.Module._extensions..js (module.js:584:10)
        at Module.load (module.js:507:32)
        at tryModuleLoad (module.js:470:12)
  ...
not ok 300 parallel/test-crypto-random
  ---
  duration_ms: 0.112
  severity: fail
  stack: |-
    assert.js:632
          throw actual;
          ^
    
    TypeError [ERR_INVALID_ARG_TYPE]: The "offset" argument must be of type number
        at assertOffset (crypto.js:743:11)
        at Object.randomFillSync (crypto.js:708:3)
        at assert.throws (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/parallel/test-crypto-random.js:158:14)
        at tryBlock (assert.js:602:5)
        at innerThrows (assert.js:621:18)
        at Function.throws (assert.js:648:3)
        at Object.<anonymous> (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/parallel/test-crypto-random.js:157:12)
        at Module._compile (module.js:573:30)
        at Object.Module._extensions..js (module.js:584:10)
        at Module.load (module.js:507:32)
  ...
not ok 303 parallel/test-crypto-sign-verify
  ---
  duration_ms: 0.174
  severity: fail
  stack: |-
    assert.js:632
          throw actual;
          ^
    
    TypeError [ERR_INVALID_ARG_TYPE]: The "options.padding" property must be of type integer
        at Sign.sign (crypto.js:317:13)
        at assert.throws (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/parallel/test-crypto-sign-verify.js:208:12)
        at tryBlock (assert.js:602:5)
        at innerThrows (assert.js:621:18)
        at Function.throws (assert.js:648:3)
        at __dirname.forEach (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/parallel/test-crypto-sign-verify.js:205:14)
        at Array.forEach (<anonymous>)
        at Object.<anonymous> (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/parallel/test-crypto-sign-verify.js:204:6)
        at Module._compile (module.js:573:30)
        at Object.Module._extensions..js (module.js:584:10)
  ...

This PR should include adjusted tests or new ones according to https://github.com/nodejs/node/blob/master/doc/guides/using-internal-errors.md#testing-new-errors

Copy link
Member

@tniessen tniessen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add tests according to this document and test your changes locally (if possible).

lib/crypto.js Outdated
@@ -302,7 +303,7 @@ Sign.prototype.update = Hash.prototype.update;

Sign.prototype.sign = function sign(options, encoding) {
if (!options)
throw new Error('No key provided to sign');
throw new errors.Error('ERR_CTYPTO_MISSING_KEY');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling: CTYPTOCRYPTO. Also, I am not sure whether we want to introduce a new error type just for this.

E('ERR_CHILD_CLOSED_BEFORE_REPLY', 'Child closed before reply received');
E('ERR_CONSOLE_WRITABLE_STREAM',
'Console expects a writable stream instance for %s');
E('ERR_CPU_USAGE', 'Unable to obtain cpu usage %s');
E('ERR_CRYPTO_MISSNG_KEY', 'No key provided to sign');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error code has no indication that this is about sign.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ERR_CRYPTO_MISSIGN_SIGN_KEY is preferable?

lib/crypto.js Outdated
@@ -728,7 +728,7 @@ function randomFill(buf, offset, size, cb) {
cb = size;
size = buf.length - offset;
} else if (typeof cb !== 'function') {
throw new TypeError('"cb" argument must be a function');
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'cb', 'function');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not ERR_INVALID_CALLBACK?

lib/crypto.js Outdated
@@ -618,7 +619,7 @@ exports.pbkdf2 = function(password,
}

if (typeof callback !== 'function')
throw new Error('No callback provided to pbkdf2');
throw new errors.Error('ERR_CRYPTO_MISSING_PBKDF2_CALLBACK');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not ERR_INVALID_CALLBACK?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this situation has limitation for PBKDF2 only and callback will be never called for other algorithms.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using ERR_INVALID_CALLBACK would still be appropriate I think

lib/crypto.js Outdated
@@ -594,7 +595,7 @@ ECDH.prototype.getPublicKey = function getPublicKey(encoding, format) {
else if (format === 'uncompressed')
f = constants.POINT_CONVERSION_UNCOMPRESSED;
else
throw new TypeError('Bad format: ' + format);
throw new error.TypeError('ERR_INVALID_FORMAT', format);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not too happy with a new error code for this single line. How about ERR_INVALID_OPT_VALUE?

lib/crypto.js Outdated
}

if (size > kMaxUint32 || size < 0) {
throw new TypeError('size must be a uint32');
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'size', 'unit32');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling: unit32uint32

lib/crypto.js Outdated
}

if (offset > kMaxUint32 || offset < 0) {
throw new TypeError('offset must be a uint32');
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'offset', 'unit32');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling: unit32uint32

lib/crypto.js Outdated
@@ -313,7 +314,7 @@ Sign.prototype.sign = function sign(options, encoding) {
if (options.padding === options.padding >> 0) {
rsaPadding = options.padding;
} else {
throw new TypeError('padding must be an integer');
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'options.padding', 'integer');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for options, please use the ERR_INVALID_OPTION_VALUE error code :-)

lib/crypto.js Outdated

if (flags && typeof flags !== 'number')
throw new TypeError('"flags" argument should be a number, if present');
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'flags', 'number or undefined');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to support multiple types, use an array

throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'flags', ['number', 'undefined']);

@rumkin
Copy link
Contributor Author

rumkin commented Aug 10, 2017

@jasnell @refack error codes are fixed.

@refack renamed ERR_CRYPTO_MISSING_KEY -> ERR_CRYPTO_MISSING_SIGN_KEY.

@jasnell jasnell added the semver-major PRs that contain breaking changes and should be released in the next major version. label Aug 11, 2017
Copy link
Member

@mhdawson mhdawson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting that no tests need to be updated... But CI run will validate that and changes LGTM.

@mhdawson
Copy link
Member

@rumkin
Copy link
Contributor Author

rumkin commented Aug 18, 2017

@mhdawson I will update tests to check error codes on the weekend.

@refack
Copy link
Contributor

refack commented Aug 18, 2017

@mhdawson failing tests are in #14724 (comment) under the fold.

@mhdawson
Copy link
Member

Ah ok thanks, did not catch that, of course CI run was very red :)

@rumkin
Copy link
Contributor Author

rumkin commented Aug 20, 2017

I've update common.expectsError source to support error.code. But I think it should be placed in another PR, isn't it?

Copy link
Contributor

@refack refack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good progress!

@@ -709,6 +709,11 @@ exports.expectsError = function expectsError(fn, settings, exact) {
assert(error instanceof type,
`${error.name} is not instance of ${type.name}`);
}
if ('code' in settings) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very good idea! I think L703 agrees with your train of thought 😉

assert.strictEqual(error.code, settings.code);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I promise that I will sleep before write code next time 😅

Copy link
Contributor

@refack refack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need a few tweaks

/^TypeError: First argument should be number, string, Buffer, TypedArray, or DataView$/;

assert.throws(() => {
common.expectsError(function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is obviously good, but you can notice that the RegExp included also the Type (/^TypeError: .../).
So you should add

  type: TypeError

to all the assertion below.

@refack
Copy link
Contributor

refack commented Aug 20, 2017

I've update common.expectsError source to support error.code. But I think it should be placed in another PR, isn't it?

Like I said, you had a good idea, it's just already there 😉

(Context: expectsError was actually introduced to first of all validate the code. That is what was missing from assert.throws.)

@refack
Copy link
Contributor

refack commented Aug 20, 2017

@@ -198,9 +203,12 @@ if (availableCurves.has('prime256v1') && availableCurves.has('secp256k1')) {
firstByte = ecdh1.getPublicKey('buffer', 'hybrid')[0];
assert(firstByte === 6 || firstByte === 7);
// format value should be string
assert.throws(() => {
common.expectsError(function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this does not throw an errors.Error:

not ok 294 parallel/test-crypto-dh
  ---
  duration_ms: 1.543
  severity: fail
  stack: |-
    assert.js:42
      throw new errors.AssertionError({
      ^
    
    AssertionError [ERR_ASSERTION]: undefined === 'ERR_INVALID_OPT_VALUE'
        at Object.<anonymous> (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/common/index.js:703:12)
        at Object.<anonymous> (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/common/index.js:509:15)
        at expectedException (assert.js:597:19)
        at innerThrows (assert.js:631:21)
        at Function.throws (assert.js:648:3)
        at Object.expectsError (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/common/index.js:742:12)
        at Object.<anonymous> (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/parallel/test-crypto-dh.js:206:10)
        at Module._compile (module.js:573:30)
        at Object.Module._extensions..js (module.js:584:10)
        at Module.load (module.js:507:32)
  ...

crypto.randomFillSync(buf, 1, 10);
}, errMessages.bufferTooSmall);

assert.throws(() => {
common.expectsError(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here the RegExp doesn't match:

not ok 300 parallel/test-crypto-random
  ---
  duration_ms: 0.225
  severity: fail
  stack: |-
    assert.js:42
      throw new errors.AssertionError({
      ^
    
    AssertionError [ERR_ASSERTION]: The "size" argument must be of type uint32 does not match /"size" .* unint32/
        at Object.<anonymous> (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/common/index.js:722:9)
        at Object.<anonymous> (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/common/index.js:509:15)
        at expectedException (assert.js:597:19)
        at innerThrows (assert.js:631:21)
        at Function.throws (assert.js:648:3)
        at Object.expectsError (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/common/index.js:742:12)
        at Object.<anonymous> (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/parallel/test-crypto-random.js:225:14)
        at Module._compile (module.js:573:30)
        at Object.Module._extensions..js (module.js:584:10)
        at Module.load (module.js:507:32)
  ...

@@ -234,9 +240,11 @@ const modSize = 1024;

// Test throws exception when key options is null
{
assert.throws(() => {
expectsError(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forgot the common.:

not ok 303 parallel/test-crypto-sign-verify
  ---
  duration_ms: 0.515
  severity: fail
  stack: |-
    /data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/parallel/test-crypto-sign-verify.js:243
      expectsError(() => {
      ^
    
    ReferenceError: expectsError is not defined
        at Object.<anonymous> (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/parallel/test-crypto-sign-verify.js:243:3)
        at Module._compile (module.js:573:30)
        at Object.Module._extensions..js (module.js:584:10)
        at Module.load (module.js:507:32)
        at tryModuleLoad (module.js:470:12)
        at Function.Module._load (module.js:462:3)
        at Function.Module.runMain (module.js:609:10)
        at startup (bootstrap_node.js:158:16)
        at bootstrap_node.js:598:3
  ...

@refack
Copy link
Contributor

refack commented Aug 20, 2017

@rumkin while the CI is a very useful tool, you should try to run the test suite locally, it'll save review back-and-forth.
See https://github.com/nodejs/node/blob/master/CONTRIBUTING.md#step-5-test

@rumkin
Copy link
Contributor Author

rumkin commented Aug 21, 2017

@refack

while the CI is a very useful tool, you should try to run the test suite locally, it'll save review back-and-forth.

Yep, I'm searching the way to run tests myself.

@BridgeAR
Copy link
Member

@BridgeAR
Copy link
Member

Ping @rumkin

@rumkin
Copy link
Contributor Author

rumkin commented Sep 14, 2017

@BridgeAR I'm here. Just bought more RAM to run test on my own.

@BridgeAR
Copy link
Member

@rumkin this needs a rebase and did you get the tests to work on your machine? They should not require a huge amount of memory though (as far as I know).

@rumkin
Copy link
Contributor Author

rumkin commented Sep 21, 2017

@BridgeAR I'm running tests in VM. That's why I had been need more RAM. Anyway I've fixed errors. And ready to rebase changes.

@rumkin
Copy link
Contributor Author

rumkin commented Sep 22, 2017

@BridgeAR @refack after rebasing I figured that there isn't significant changes in my PR. The only difference was in error codes. So I'm closing this PR. Thanks for help.

@rumkin rumkin closed this Sep 22, 2017
@BridgeAR
Copy link
Member

@rumkin I am sorry to head that. The refactoring of the crypto module landed just a few days ago. Thanks a lot for your contribution anyway!

@rumkin
Copy link
Contributor Author

rumkin commented Sep 23, 2017

@BridgeAR It's ok. Now we sure everything done right. I think it's very important for crypto module.

@refack refack removed their assignment Oct 12, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crypto Issues and PRs related to the crypto subsystem. errors Issues and PRs related to JavaScript errors originated in Node.js core. semver-major PRs that contain breaking changes and should be released in the next major version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants