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

lib: generalize handling in assert.deepEqual() #3124

Closed
wants to merge 4 commits into from

Conversation

Trott
Copy link
Member

@Trott Trott commented Sep 30, 2015

Error objects have non-enumerable properties. So, unexpectedly,
assert.deepEqual(new Error('a'), new Error('b')); will not throw. This
commit changes that behavior.

Fixes: #3122

@Fishrock123 Fishrock123 added the assert Issues and PRs related to the assert subsystem. label Sep 30, 2015
@thefourtheye
Copy link
Contributor

Whenever there is a change suggested in this module I judge that by this comment #2315 (comment). If we go by that, this change is not necessary as assert is not a general purpose module.

@ChALkeR
Copy link
Member

ChALkeR commented Sep 30, 2015

Is this a semver-major? @rvagg

@Trott
Copy link
Member Author

Trott commented Sep 30, 2015

@thefourtheye Yes, if that's the standard, then this is probably not necessary. I say "probably" because I wonder if any of the checks on things like err.message in Node's own tests would be preferable to do with something like assert.deepEqual() if it worked on tests. Quite possibly not. I might start looking though.

More importantly, perhaps: If the assert module is not a general purpose module, that fact should be reflected in the docs.

@rvagg rvagg added the semver-major PRs that contain breaking changes and should be released in the next major version. label Sep 30, 2015
@ChALkeR
Copy link
Member

ChALkeR commented Sep 30, 2015

@Trott, @domenic It's a bit too late for making the assert module interal, as it looks to me. A doc-only deprecation would do no harm, but it's going to stay in that state forever.

It's directly used by at least 11% of modules on npmjs (a quick grep for require\(.assert\.) found it in 20734 packages out of 186231, and I'm sure there are false negatives). Mostly in tests, benchmarks, and specs, but still.

Update: Without the .*/(tests?|bench|benchmarks?|spec|examples?)/.* paths — 6311 packages (3%).

@rvagg
Copy link
Member

rvagg commented Sep 30, 2015

Yes, has to be semver-major I reckon, also I'm not sure this approach is consistent, have a look at how RegExp is handled, comparing only a strict list of properties but this change will compare any properties attached to an Error—attaching custom properties to an Error is fairly common too (although not so for RegExp so perhaps there's an argument to be made there, but the inconsistency concerns me more).

@Fishrock123
Copy link
Contributor

JavaScript is an awful language sometimes haha. I agree with Rod's sentiment, but I think the frequency of use would warrant this enough.

If nothing else, we could probably get it into deepStrictEquals. :)

@Trott
Copy link
Member Author

Trott commented Oct 8, 2015

I'm thinking I should close this PR and instead update the docs to reflect that:

  • this assertion library is intended to only meet the needs of the Node.js project and people are encouraged to use userland assertion libraries instead (there's certainly enough of them!)
  • comparison is only with enumerable properties
  • that can cause unexpected results like this one
  • show a workaround for it if there is a reasonably compact example workaround (such as maybe just using assert.throws() with the error type checking and message checking options)

@Trott
Copy link
Member Author

Trott commented Oct 10, 2015

@rvagg, @Fishrock123: Since it's already semver-major, might an appropriate course of action be to run RegExp (and maybe a few other things) through this more rigorous checking? Assuming it doesn't bork any of our tests, it seems like that might streamline the code a bit. It's semver-major already, so why not take the opportunity to streamline the code a bit?

@Trott
Copy link
Member Author

Trott commented Oct 11, 2015

Just pushed something to remove special handling for Error, Buffer, and RegExp. Added a tiny bit of hopefully-straightforward special handling for Array and String (which is to ignore the length property if they are being compared against something that doesn't have a length property). All tests still pass. Still semver major, but I feel much better about this. Seems less hacky. PTAL @rvagg @Fishrock123

Still could use a doc update to clarify some finer points, but that could be a separate PR, as this is all consistent with existing docs.

@Trott
Copy link
Member Author

Trott commented Oct 11, 2015

@rvagg
Copy link
Member

rvagg commented Oct 12, 2015

yeah, I don't know, this is pretty significant, perhaps we need to include @nodejs/tsc on this for more opinions

@trevnorris
Copy link
Contributor

This PR looks like it's attempting to achieve some sort of theoretical completeness. Which I don't disagree with, but on this route you must seriously consider also doing proper comparisons of any Symbols also attached to the object.

Error objects have non-enumerable properties. So, unexpectedly,
assert.deepEqual(new Error('a'), new Error('b')) will not throw an
AssertionError. This commit changes that behavior.

Fixes: nodejs#3122
@Trott
Copy link
Member Author

Trott commented Oct 12, 2015

@trevnorris Symbols added. Thanks for that!

@domenic
Copy link
Contributor

domenic commented Oct 12, 2015

I'm thinking I should close this PR and instead update the docs to reflect that:

This seems better to me.

@Trott, @domenic It's a bit too late for making the assert module interal, as it looks to me. A doc-only deprecation would do no harm, but it's going to stay in that state forever.

Nobody suggested making it internal or deprecating it. Just, not changing it.

@Trott
Copy link
Member Author

Trott commented Oct 12, 2015

@domenic Can you elaborate a bit on why you favor the doc-only approach but not a deprecation? I'm assuming deprecation could just mean sticking a deprecation notice in the docs but not doing anything at all in the code. Maybe we just have different ideas about what "deprecation" might entail.

The close-in-favor-of-doc-PR was how I felt when this change was adding additional special handling for Error objects. It's evolved, though, to where it's removing special handling for things like RegExp and Buffer and still coming up with the right answer. At the same time, it's fixing at least one thing I would consider a bug (it's now handling Error in a way that conforms with naive user expectations) and does not break any of our tests. It probably wouldn't break many tests in the wild (although it might surface tests that are passing that actually shouldn't!).

@Trott
Copy link
Member Author

Trott commented Oct 12, 2015

@domenic
Copy link
Contributor

domenic commented Oct 12, 2015

I just think that contributors and core team members should not spend time working on the assert module. They especially shouldn't be doing so in a way that changes behavior in observable ways that could break programs using it.

Maybe it would be helpful to add something to the docs saying its behavior won't be changed, so that people don't file issues on it. And maybe it'd even be interesting to explain why---because the assert module is developed so that Node.js can test itself, not so that you can write your own tests. I don't know if you'd call that a deprecation or not.

@Trott
Copy link
Member Author

Trott commented Oct 12, 2015

@domenic Thanks, that's very clear. I guess regardless of what happens to this PR, the doc change is a good idea.

@Trott Trott changed the title lib: assert.deepEqual() fix for Error objects lib: generalize handling in assert.deepEqual() Oct 12, 2015
@Trott
Copy link
Member Author

Trott commented Oct 12, 2015

Proposed doc-only update at #3330. I'm still in favor of the changes here, but regardless, the docs should reflect the current status.

@Trott
Copy link
Member Author

Trott commented Oct 16, 2015

Based on the audio from the most recent TSC meeting, I'm going to close this PR. Assert will be set to Stability Index Locked, users can generally be gently encouraged to use userland assertion libraries, and anything Node core might need added to Assert should probably go in test/common.js instead.

@Trott Trott closed this Oct 16, 2015
Trott added a commit to Trott/io.js that referenced this pull request Oct 16, 2015
Trott added a commit to Trott/io.js that referenced this pull request Oct 19, 2015
Assert is now locked. Userland alternatives should be used. Assert is
for testing Node.js itself.

Document potentially surprising use of enumerable properties only in
deep equality assertions.

Ref: nodejs#3124
Ref: nodejs#3122

PR-URL: nodejs#3330
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Fedor Indutny <fedor@indutny.com>
Reviewed-By: Rod Vagg <rod@vagg.org>
Trott added a commit that referenced this pull request Oct 21, 2015
Assert is now locked. Userland alternatives should be used. Assert is
for testing Node.js itself.

Document potentially surprising use of enumerable properties only in
deep equality assertions.

Ref: #3124
Ref: #3122

PR-URL: #3330
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Fedor Indutny <fedor@indutny.com>
Reviewed-By: Rod Vagg <rod@vagg.org>
Trott added a commit that referenced this pull request Oct 26, 2015
Assert is now locked. Userland alternatives should be used. Assert is
for testing Node.js itself.

Document potentially surprising use of enumerable properties only in
deep equality assertions.

Ref: #3124
Ref: #3122

PR-URL: #3330
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Fedor Indutny <fedor@indutny.com>
Reviewed-By: Rod Vagg <rod@vagg.org>
Trott added a commit that referenced this pull request Oct 29, 2015
Assert is now locked. Userland alternatives should be used. Assert is
for testing Node.js itself.

Document potentially surprising use of enumerable properties only in
deep equality assertions.

Ref: #3124
Ref: #3122

PR-URL: #3330
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Fedor Indutny <fedor@indutny.com>
Reviewed-By: Rod Vagg <rod@vagg.org>
@Trott Trott deleted the assert-deepEqual-error branch January 13, 2022 22:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
assert Issues and PRs related to the assert subsystem. 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