expect(["....big string here"]).toBe("another 3MB string");
Writing code like this, jest will throw RangeError, here is the error message:
● Test suite failed to run
RangeError: Maximum call stack size exceeded
at String.match (<anonymous>)
at exports.separateMessageFromStack.content (node_modules/jest-message-util/build/index.js:368:32)
at Array.map (<anonymous>)
the Array expect function got has an item that is an about 3MB string (base64 image), and toBe got the same base64 String.
like above.
should fail the test, but not throw range error
System:
OS: macOS 10.14.6
CPU: (4) x64 Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz
Binaries:
Node: 11.2.0 - ~/.nvm/versions/node/v11.2.0/bin/node
Yarn: 1.12.3 - /usr/local/bin/yarn
npm: 6.4.1 - ~/.nvm/versions/node/v11.2.0/bin/npm
npmPackages:
jest: ^23.6.0 => 23.6.0
Does it also happen with jest@24 or jest@next? cc @pedrottimark.
Also a repro would be very helpful
node.js doesn't seem to like really long strings. I'm able to reproduce the bug and I think I found a fix. But testing this takes ages. Especially with my fix, as the console output grinds to a halt.
Anyway: string.match() crashes, probably due to a recursive approach. I'm not sure if the used regular expression can be changed to avoid this recursion.
// Problematic regex:
const messageMatch = content.match(/(^(.|\n)*?(?=\n\s*at\s.*\:\d*\:\d*))/);
let message = messageMatch ? messageMatch[0] : 'Error';
const stack = messageMatch ? content.slice(message.length) : content;
My monkeypatched fix:
const callstackPos = content.search(/((\n\s*at\s.*\:\d*\:\d*))/);
let message = callstackPos ? content.substring(0, callstackPos) : 'Error';
const stack = callstackPos ? content.substring(callstackPos+1) : content;
That should work the same, but cuts match() out, instead relying on cutting by hand.
Reproducion:
it("compares the strings correcty", () => {
expect(string1 + "w").toBe(string1);
});
whereas string1 is just a 3000000 character long string I randomly generated (be aware: some IDEs might not like this).
While it fails here https://github.com/facebook/jest/blob/736edd2ea6c9aadfb6e8794ecdc8a726f8a76b1a/packages/jest-message-util/src/index.ts#L358-L360, I think it makes more sense to avoid huge strings here: https://github.com/facebook/jest/blob/736edd2ea6c9aadfb6e8794ecdc8a726f8a76b1a/packages/jest-matcher-utils/src/index.ts#L307-L313 rather than trying to fix the regex part. This ends up generating a huge string, which is used when throwing the assertion error, which we later run the regex against. I think such a huge string is not useful anyways
That said, the change @StringEpsilon suggests seems reasonable regardless?
Yes, the way Jest hangs is as annoying as #1772 and #5392 but for different reason
Because base64 strings do not contain newlines, it was:
MAX_DIFF_STRING_LENGTHCan y’all suggest any good examples of software tools that Jest might follow to limit:
in the report when a matcher fails?
@Genuifx To help me think what is relevant information that Jest should provide, the type mismatch of array as received value and string as expected value was which of the following:
I'm not entirely sure if a unit test suite does that, but think a good way of dealing with overly long lines would just be to chop to the relevant section. That would be the start of the differences + whatever surroundings can be added reasonably.
Samples for comparing against SBjb21wcmVoZW5zaXZlIEphdmFTY3JpcHQgdGVzdGluZyBzb2x1dGlvbi4gV29ya3Mgb3V0IG9mIHRoZSBib3ggZm9yIG1vc3QgSmF2YVNjcmlwdCBwcm9qZWN0cy4K
Expected: "SBjb21wcmVoZW5zaXZlIEphdmFTY3JpcHQgdGVz" + [88]
Received: "_Z_Bjb21wcmVoZW5zaXZlIEphdmFTY3JpcHQgdGVz" + [88]
Expected: [66] + "Mgb3V0I_G9ml_HRoZSBib3ggZm9yIG1vc" + [31 ]
Receveived: [66] + "Mgb3V0I_G9ML_HRoZSBib3ggZm9yIG1vc" + [31]
Expected: [80] + "ZSBib3ggZm9yIG1vc3QgSmF2YVNjcmlwdCBwcm9qZWN0cy4_K_"
Received: [80] + "ZSBib3ggZm9yIG1vc3QgSmF2YVNjcmlwdCBwcm9qZWN0cy4_L_"
It's not entirely uncommon for compilers or intrepeters to chop lines to the relevant section. I'm not entirely sure how much overhead this would introduce. I'm also not sure about the UX aspects of chopping strings that should be equal but aren't (i.E. introducing headaches to the guy debugging that test)
@pedrottimark error in the test is preferred. Actually, That was my bug while mocking some kind of function.
@StringEpsilon I was doing redux compatible work for mini-app, one case needs consider is the store's data is too large to connect the page (every single time setData call only 1024kb data can be transferred between threads), so I used jest writing some related test suites.
I was getting this error with .toMatchObject so to solve this I JSON.stringified the object and checked toMatch instead of checking the object.
This happen when I use functions with two ways. This will be generate call stack error because Javascript is single thread, example:
const a = () => {
const b = b();
const c = "hello"
return b + c
}
const b = () => {
const a = a()
const c = "hello"
return a + c
}
Function a call function b and function b call function a, this will fill the call stack and generate this error