From d6f1008cdd5580a8ee0b9676df1c25bdb21403c6 Mon Sep 17 00:00:00 2001 From: Nicholas Paun Date: Thu, 5 Sep 2024 11:25:10 -0700 Subject: [PATCH] Add more brotli tests --- .../api/node/tests/zlib-nodejs-test.js | 128 +++++++++++++----- 1 file changed, 96 insertions(+), 32 deletions(-) diff --git a/src/workerd/api/node/tests/zlib-nodejs-test.js b/src/workerd/api/node/tests/zlib-nodejs-test.js index 545a00910435..2e4dc020547e 100644 --- a/src/workerd/api/node/tests/zlib-nodejs-test.js +++ b/src/workerd/api/node/tests/zlib-nodejs-test.js @@ -1486,7 +1486,6 @@ export const zlibFromString = { // Test taken from // https://github.com/nodejs/node/blob/fc02b88f89f8d5abf5ee4414a1026444c18d77b3/test/parallel/test-zlib-empty-buffer.js -// TODO(soon): enable brotli cases once implemented export const zlibEmptyBuffer = { async test() { const emptyBuffer = Buffer.alloc(0); @@ -1495,11 +1494,11 @@ export const zlibEmptyBuffer = { [zlib.deflateRawSync, zlib.inflateRawSync, 'raw sync'], [zlib.deflateSync, zlib.inflateSync, 'deflate sync'], [zlib.gzipSync, zlib.gunzipSync, 'gzip sync'], - //[ zlib.brotliCompressSync, zlib.brotliDecompressSync, 'br sync' ], + [zlib.brotliCompressSync, zlib.brotliDecompressSync, 'br sync'], [promisify(zlib.deflateRaw), promisify(zlib.inflateRaw), 'raw'], [promisify(zlib.deflate), promisify(zlib.inflate), 'deflate'], [promisify(zlib.gzip), promisify(zlib.gunzip), 'gzip'], - //[ promisify(zlib.brotliCompress), promisify(zlib.brotliDecompress), 'br' ], + [promisify(zlib.brotliCompress), promisify(zlib.brotliDecompress), 'br'], ]) { const compressed = await compress(emptyBuffer); const decompressed = await decompress(compressed); @@ -1730,10 +1729,9 @@ export const closeAfterWrite = { }, }; -const BIG_DATA = 'horse'.repeat(50_000) + 'cow'.repeat(49_000); - export const inflateSyncTest = { test() { + const BIG_DATA = 'horse'.repeat(50_000) + 'cow'.repeat(49_000); assert.strictEqual( zlib.inflateSync(zlib.deflateSync(BIG_DATA)).toString(), BIG_DATA @@ -1787,12 +1785,6 @@ export const deflateSyncTest = { return buf.fill(0x0, 9, 10); } - assert.throws( - () => - zlib.deflateSync(BIG_DATA, { maxOutputLength: 64 }).toString('base64'), - new RangeError('Memory limit exceeded') - ); - assert.strictEqual( zlib .deflateSync('bird bird bird', { windowBits: 11, level: 4 }) @@ -1800,15 +1792,6 @@ export const deflateSyncTest = { 'OE9LyixKUUiCEQAmfgUk' ); - assert.strictEqual( - zlib - .deflateSync('what happens if you do not flush?', { - finishFlush: zlib.constants.Z_NO_FLUSH, - }) - .toString('base64'), - 'eJw=' - ); - assert.deepStrictEqual( maskOsId( zlib.gzipSync('water, water, everywhere, nor any drop to drink') @@ -1827,8 +1810,7 @@ export const prematureEnd = { for (const [compress, decompressor] of [ [zlib.deflateRawSync, zlib.createInflateRaw], [zlib.deflateSync, zlib.createInflate], - // TODO(soon): Enable this once brotli is implemented. - // [zlib.brotliCompressSync, zlib.createBrotliDecompress], + [zlib.brotliCompressSync, zlib.createBrotliDecompress], ]) { const compressed = compress(input); const trailingData = Buffer.from('not valid compressed data'); @@ -1971,13 +1953,12 @@ export const convenienceMethods = { ['gzip', 'unzip', 'Gzip', 'Unzip'], ['deflate', 'inflate', 'Deflate', 'Inflate'], ['deflateRaw', 'inflateRaw', 'DeflateRaw', 'InflateRaw'], - // TODO(soon): Enable this once brotli functions are implemented - // [ - // 'brotliCompress', - // 'brotliDecompress', - // 'BrotliCompress', - // 'BrotliDecompress', - // ], + [ + 'brotliCompress', + 'brotliDecompress', + 'BrotliCompress', + 'BrotliDecompress', + ], ]) { { const { promise, resolve } = Promise.withResolvers(); @@ -2145,6 +2126,89 @@ export const brotliFromString = { }, }; +// Test taken from +// https://github.com/nodejs/node/blob/26eb062a9b9c0ae8cee9cb5c378e43bca363207c/test/parallel/test-zlib-maxOutputLength.js +export const maxOutputLength = { + async test() { + const encoded = Buffer.from('G38A+CXCIrFAIAM=', 'base64'); + + // Async + { + const { promise, resolve } = Promise.withResolvers(); + zlib.brotliDecompress(encoded, { maxOutputLength: 64 }, (err) => { + // TODO(soon): Make error the same as NodeJS + assert.match(err.message, /Memory limit exceeded/); + resolve(); + }); + await promise; + } + + // Sync + assert.throws(function () { + zlib.brotliDecompressSync(encoded, { maxOutputLength: 64 }); + }, RangeError); + + // Async + { + const { promise, resolve } = Promise.withResolvers(); + zlib.brotliDecompress(encoded, { maxOutputLength: 256 }, function (err) { + assert.strictEqual(err, null); + resolve(); + }); + + await promise; + } + + // Sync + zlib.brotliDecompressSync(encoded, { maxOutputLength: 256 }); + }, +}; + +// Test taken from +// https://github.com/nodejs/node/blob/24302c9fe94e1dd755ac8a8cc1f6aa4444f75cb3/test/parallel/test-zlib-invalid-arg-value-brotli-compress.js +export const invalidArgValueBrotliCompress = { + test() { + const opts = { + params: { + [zlib.constants.BROTLI_PARAM_MODE]: 'lol', + }, + }; + + // TODO(soon): Node's test invokes BrotliCompress without new, but we barf if you try that. + assert.throws(() => new zlib.BrotliCompress(opts), { + code: 'ERR_INVALID_ARG_TYPE', + }); + }, +}; + +// Test taken from +// https://github.com/nodejs/node/blob/24302c9fe94e1dd755ac8a8cc1f6aa4444f75cb3/test/parallel/test-zlib-brotli-flush.js +export const brotliFlush = { + async test() { + const deflater = new zlib.BrotliCompress(); + + const chunk = Buffer.from('/9j/4AAQSkZJRgABAQEASA==', 'base64'); + const expectedFull = Buffer.from('iweA/9j/4AAQSkZJRgABAQEASA==', 'base64'); + let actualFull; + + { + const { promise, resolve } = Promise.withResolvers(); + deflater.write(chunk, function () { + deflater.flush(function () { + const bufs = []; + let buf; + while ((buf = deflater.read()) !== null) bufs.push(buf); + actualFull = Buffer.concat(bufs); + resolve(); + }); + }); + + await promise; + } + assert.deepStrictEqual(actualFull, expectedFull); + }, +}; + // Node.js tests relevant to zlib // // - [ ] test-zlib-brotli-16GB.js @@ -2152,7 +2216,7 @@ export const brotliFromString = { // - [ ] test-zlib-flush-drain.js // - [ ] test-zlib-invalid-input-memory.js // - [ ] test-zlib-sync-no-event.js -// - [ ] test-zlib-brotli-flush.js +// - [x] test-zlib-brotli-flush.js // - [x] test-zlib-crc32.js // - [ ] test-zlib-flush-drain-longblock.js // - [ ] test-zlib.js @@ -2165,7 +2229,7 @@ export const brotliFromString = { // - [x] test-zlib-brotli-from-string.js // - [x] test-zlib-deflate-constructors.js // - [x] test-zlib-flush.js -// - [ ] test-zlib-maxOutputLength.js +// - [x] test-zlib-maxOutputLength.js // - [x] test-zlib-unzip-one-byte-chunks.js // - [ ] test-zlib-brotli.js // - [ ] test-zlib-deflate-raw-inherits.js @@ -2194,7 +2258,7 @@ export const brotliFromString = { // - [x] test-zlib-zero-windowBits.js // - [x] test-zlib-close-in-ondata.js // - [x] test-zlib-empty-buffer.js -// - [ ] test-zlib-invalid-arg-value-brotli-compress.js +// - [x] test-zlib-invalid-arg-value-brotli-compress.js // - [ ] test-zlib-random-byte-pipes.js // - [x] test-zlib-const.js // - [x] test-zlib-failed-init.js