Signed-off-by: James M Snell <jasnell@gmail.com> Assisted-By: Claude/Opus 4.6 PR-URL: https://github.com/nodejs/node/pull/62066 Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
119 lines
3.6 KiB
JavaScript
119 lines
3.6 KiB
JavaScript
// Flags: --experimental-stream-iter
|
|
'use strict';
|
|
|
|
// Coverage tests for transform.js: abort cleanup, strategy/params options,
|
|
// early consumer exit triggering finally block.
|
|
|
|
const common = require('../common');
|
|
const assert = require('assert');
|
|
const {
|
|
from,
|
|
pull,
|
|
bytes,
|
|
text,
|
|
} = require('stream/iter');
|
|
const {
|
|
compressGzip,
|
|
decompressGzip,
|
|
compressDeflate,
|
|
decompressDeflate,
|
|
compressBrotli,
|
|
decompressBrotli,
|
|
compressZstd,
|
|
decompressZstd,
|
|
} = require('zlib/iter');
|
|
const { constants } = require('zlib');
|
|
|
|
async function roundTrip(input, compress, decompress) {
|
|
return text(pull(from(input), compress, decompress));
|
|
}
|
|
|
|
// Abort mid-compression triggers finally cleanup
|
|
async function testAbortMidCompression() {
|
|
const ac = new AbortController();
|
|
const largeInput = 'x'.repeat(100_000);
|
|
const compressed = pull(from(largeInput), compressGzip(),
|
|
{ signal: ac.signal });
|
|
const iter = compressed[Symbol.asyncIterator]();
|
|
|
|
// Read one batch then abort
|
|
const first = await iter.next();
|
|
assert.strictEqual(first.done, false);
|
|
ac.abort();
|
|
await assert.rejects(iter.next(), { name: 'AbortError' });
|
|
}
|
|
|
|
// Early consumer exit (break from for-await) triggers finally
|
|
async function testEarlyConsumerExit() {
|
|
const largeInput = 'y'.repeat(100_000);
|
|
const compressed = pull(from(largeInput), compressGzip());
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
for await (const batch of compressed) {
|
|
break; // Early exit — should trigger finally block cleanup
|
|
}
|
|
// If we get here without hanging or crashing, cleanup worked
|
|
}
|
|
|
|
// Gzip with explicit strategy option
|
|
async function testGzipWithStrategy() {
|
|
const input = 'strategy test data '.repeat(100);
|
|
const c = compressGzip({ strategy: constants.Z_DEFAULT_STRATEGY });
|
|
const result = await roundTrip(input, c, decompressGzip());
|
|
assert.strictEqual(result, input);
|
|
}
|
|
|
|
// Deflate with Z_FIXED strategy
|
|
async function testDeflateWithFixedStrategy() {
|
|
const input = 'fixed strategy '.repeat(100);
|
|
const c = compressDeflate({ strategy: constants.Z_FIXED });
|
|
const result = await roundTrip(input, c, decompressDeflate());
|
|
assert.strictEqual(result, input);
|
|
}
|
|
|
|
// Brotli with custom quality param
|
|
async function testBrotliWithParams() {
|
|
const input = 'brotli params test '.repeat(100);
|
|
const params = { [constants.BROTLI_PARAM_QUALITY]: 5 };
|
|
const result = await roundTrip(input, compressBrotli({ params }),
|
|
decompressBrotli());
|
|
assert.strictEqual(result, input);
|
|
}
|
|
|
|
// Zstd with custom compression level param
|
|
async function testZstdWithParams() {
|
|
const input = 'zstd params test '.repeat(100);
|
|
const params = { [constants.ZSTD_c_compressionLevel]: 10 };
|
|
const result = await roundTrip(input, compressZstd({ params }),
|
|
decompressZstd());
|
|
assert.strictEqual(result, input);
|
|
}
|
|
|
|
// Gzip with custom chunkSize
|
|
async function testGzipWithChunkSize() {
|
|
const input = 'chunk size test';
|
|
const c = compressGzip({ chunkSize: 256 });
|
|
const d = decompressGzip({ chunkSize: 256 });
|
|
const result = await roundTrip(input, c, d);
|
|
assert.strictEqual(result, input);
|
|
}
|
|
|
|
// Invalid chunkSize throws when transform is invoked
|
|
async function testInvalidChunkSize() {
|
|
const tx = compressGzip({ chunkSize: 8 });
|
|
await assert.rejects(
|
|
async () => await bytes(pull(from('data'), tx)),
|
|
{ code: 'ERR_OUT_OF_RANGE' },
|
|
);
|
|
}
|
|
|
|
Promise.all([
|
|
testAbortMidCompression(),
|
|
testEarlyConsumerExit(),
|
|
testGzipWithStrategy(),
|
|
testDeflateWithFixedStrategy(),
|
|
testBrotliWithParams(),
|
|
testZstdWithParams(),
|
|
testGzipWithChunkSize(),
|
|
testInvalidChunkSize(),
|
|
]).then(common.mustCall());
|