From b3d08042bda12385e98c7dab195ec3ac4cb2929e Mon Sep 17 00:00:00 2001 From: LiviaMedeiros Date: Thu, 25 Apr 2024 05:26:40 +0800 Subject: [PATCH 1/2] test: limit stack size in `test-error-serdes` --- test/parallel/test-error-serdes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/parallel/test-error-serdes.js b/test/parallel/test-error-serdes.js index da09e6ed0a4d9f..af9b6558adcfc2 100644 --- a/test/parallel/test-error-serdes.js +++ b/test/parallel/test-error-serdes.js @@ -1,4 +1,4 @@ -// Flags: --expose-internals +// Flags: --expose-internals --stack-size=128 'use strict'; require('../common'); const assert = require('assert'); From af75425ed3402ce1dffc736df7f27f40263b24c8 Mon Sep 17 00:00:00 2001 From: LiviaMedeiros Date: Fri, 26 Apr 2024 23:34:27 +0800 Subject: [PATCH 2/2] [CI TEST, DO NOT MERGE] extract stack exhaustion test --- .../test-error-serdes-recursive-fast.js | 29 +++++++++++++++++++ .../test-error-serdes-recursive-slow.js | 29 +++++++++++++++++++ test/parallel/test-error-serdes-recursive.js | 29 +++++++++++++++++++ test/parallel/test-error-serdes.js | 19 +----------- 4 files changed, 88 insertions(+), 18 deletions(-) create mode 100644 test/parallel/test-error-serdes-recursive-fast.js create mode 100644 test/parallel/test-error-serdes-recursive-slow.js create mode 100644 test/parallel/test-error-serdes-recursive.js diff --git a/test/parallel/test-error-serdes-recursive-fast.js b/test/parallel/test-error-serdes-recursive-fast.js new file mode 100644 index 00000000000000..5bca4da0c95080 --- /dev/null +++ b/test/parallel/test-error-serdes-recursive-fast.js @@ -0,0 +1,29 @@ +// Flags: --expose-internals --stack-size=128 +'use strict'; +require('../common'); +const assert = require('assert'); +const { serializeError, deserializeError } = require('internal/error_serdes'); + +function cycle(err) { + return deserializeError(serializeError(err)); +} + +class ErrorWithCyclicCause extends Error { + get cause() { + return new ErrorWithCyclicCause(); + } +} +const errorWithCyclicCause = Object + .defineProperty(new Error('Error with cause'), 'cause', { get() { return errorWithCyclicCause; } }); + +assert.strictEqual(Object.hasOwn(cycle(errorWithCyclicCause), 'cause'), true); + +// When the cause is cyclic, it is serialized until Maxiumum call stack size is reached +let depth = 0; +let e = cycle(new ErrorWithCyclicCause('Error with cause')); +while (e.cause) { + e = e.cause; + depth++; +} +assert(depth > 1); +console.log('Successfully completed stack exhaust test at', depth); diff --git a/test/parallel/test-error-serdes-recursive-slow.js b/test/parallel/test-error-serdes-recursive-slow.js new file mode 100644 index 00000000000000..980c67ed4f40f7 --- /dev/null +++ b/test/parallel/test-error-serdes-recursive-slow.js @@ -0,0 +1,29 @@ +// Flags: --expose-internals --stack-size=3072 +'use strict'; +require('../common'); +const assert = require('assert'); +const { serializeError, deserializeError } = require('internal/error_serdes'); + +function cycle(err) { + return deserializeError(serializeError(err)); +} + +class ErrorWithCyclicCause extends Error { + get cause() { + return new ErrorWithCyclicCause(); + } +} +const errorWithCyclicCause = Object + .defineProperty(new Error('Error with cause'), 'cause', { get() { return errorWithCyclicCause; } }); + +assert.strictEqual(Object.hasOwn(cycle(errorWithCyclicCause), 'cause'), true); + +// When the cause is cyclic, it is serialized until Maxiumum call stack size is reached +let depth = 0; +let e = cycle(new ErrorWithCyclicCause('Error with cause')); +while (e.cause) { + e = e.cause; + depth++; +} +assert(depth > 1); +console.log('Successfully completed stack exhaust test at', depth); diff --git a/test/parallel/test-error-serdes-recursive.js b/test/parallel/test-error-serdes-recursive.js new file mode 100644 index 00000000000000..898da775aa3129 --- /dev/null +++ b/test/parallel/test-error-serdes-recursive.js @@ -0,0 +1,29 @@ +// Flags: --expose-internals +'use strict'; +require('../common'); +const assert = require('assert'); +const { serializeError, deserializeError } = require('internal/error_serdes'); + +function cycle(err) { + return deserializeError(serializeError(err)); +} + +class ErrorWithCyclicCause extends Error { + get cause() { + return new ErrorWithCyclicCause(); + } +} +const errorWithCyclicCause = Object + .defineProperty(new Error('Error with cause'), 'cause', { get() { return errorWithCyclicCause; } }); + +assert.strictEqual(Object.hasOwn(cycle(errorWithCyclicCause), 'cause'), true); + +// When the cause is cyclic, it is serialized until Maxiumum call stack size is reached +let depth = 0; +let e = cycle(new ErrorWithCyclicCause('Error with cause')); +while (e.cause) { + e = e.cause; + depth++; +} +assert(depth > 1); +console.log('Successfully completed stack exhaust test at', depth); diff --git a/test/parallel/test-error-serdes.js b/test/parallel/test-error-serdes.js index af9b6558adcfc2..42d2bd9466759c 100644 --- a/test/parallel/test-error-serdes.js +++ b/test/parallel/test-error-serdes.js @@ -1,4 +1,4 @@ -// Flags: --expose-internals --stack-size=128 +// Flags: --expose-internals 'use strict'; require('../common'); const assert = require('assert'); @@ -57,17 +57,10 @@ class ErrorWithThowingCause extends Error { throw new Error('err'); } } -class ErrorWithCyclicCause extends Error { - get cause() { - return new ErrorWithCyclicCause(); - } -} const errorWithCause = Object .defineProperty(new Error('Error with cause'), 'cause', { get() { return { foo: 'bar' }; } }); const errorWithThrowingCause = Object .defineProperty(new Error('Error with cause'), 'cause', { get() { throw new Error('err'); } }); -const errorWithCyclicCause = Object - .defineProperty(new Error('Error with cause'), 'cause', { get() { return errorWithCyclicCause; } }); assert.strictEqual(cycle(new Error('Error with cause', { cause: 0 })).cause, 0); assert.strictEqual(cycle(new Error('Error with cause', { cause: -1 })).cause, -1); @@ -79,19 +72,9 @@ assert.strictEqual(cycle(new Error('Error with cause', { cause: 'foo' })).cause, assert.deepStrictEqual(cycle(new Error('Error with cause', { cause: new Error('err') })).cause, new Error('err')); assert.deepStrictEqual(cycle(errorWithCause).cause, { foo: 'bar' }); assert.strictEqual(Object.hasOwn(cycle(errorWithThrowingCause), 'cause'), false); -assert.strictEqual(Object.hasOwn(cycle(errorWithCyclicCause), 'cause'), true); assert.deepStrictEqual(cycle(new ErrorWithCause('Error with cause')).cause, new Error('err')); assert.strictEqual(cycle(new ErrorWithThowingCause('Error with cause')).cause, undefined); assert.strictEqual(Object.hasOwn(cycle(new ErrorWithThowingCause('Error with cause')), 'cause'), false); -// When the cause is cyclic, it is serialized until Maxiumum call stack size is reached -let depth = 0; -let e = cycle(new ErrorWithCyclicCause('Error with cause')); -while (e.cause) { - e = e.cause; - depth++; -} -assert(depth > 1); - { const err = new ERR_INVALID_ARG_TYPE('object', 'Object', 42);