Skip to content
File

Blob: src/workerd/api/node/tests/zlib-nodejs-test.js

javascript3022 lines
1// Copyright (c) 2024 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4import assert from 'node:assert';
5import { Buffer } from 'node:buffer';
6import {
7 Readable,
8 Writable,
9 Stream,
10 getDefaultHighWaterMark,
11} from 'node:stream';
12import { inspect, promisify } from 'node:util';
13import { mock } from 'node:test';
14import zlib from 'node:zlib';
15import crypto from 'node:crypto';
16 
17// The following test data comes from
18// https://github.com/zlib-ng/zlib-ng/blob/5401b24/test/test_crc32.cc
19// test_crc32.cc -- crc32 unit test
20// Copyright (C) 2019-2021 IBM Corporation
21// Authors: Rogerio Alves <rogealve@br.ibm.com>
22// Matheus Castanho <msc@linux.ibm.com>
23// For conditions of distribution and use, see copyright notice in zlib.h
24export const crc32Test = {
25 test() {
26 const tests = [
27 [0x0, 0x0, 0, 0x0],
28 [0xffffffff, 0x0, 0, 0x0],
29 [0x0, 0x0, 255, 0x0] /* BZ 174799. */,
30 [0x0, 0x0, 256, 0x0],
31 [0x0, 0x0, 257, 0x0],
32 [0x0, 0x0, 32767, 0x0],
33 [0x0, 0x0, 32768, 0x0],
34 [0x0, 0x0, 32769, 0x0],
35 [0x0, '', 0, 0x0],
36 [0xffffffff, '', 0, 0xffffffff],
37 [0x0, 'abacus', 6, 0xc3d7115b],
38 [0x0, 'backlog', 7, 0x269205],
39 [0x0, 'campfire', 8, 0x22a515f8],
40 [0x0, 'delta', 5, 0x9643fed9],
41 [0x0, 'executable', 10, 0xd68eda01],
42 [0x0, 'file', 4, 0x8c9f3610],
43 [0x0, 'greatest', 8, 0xc1abd6cd],
44 [0x0, 'hello', 5, 0x3610a686],
45 [0x0, 'inverter', 8, 0xc9e962c9],
46 [0x0, 'jigsaw', 6, 0xce4e3f69],
47 [0x0, 'karate', 6, 0x890be0e2],
48 [0x0, 'landscape', 9, 0xc4e0330b],
49 [0x0, 'machine', 7, 0x1505df84],
50 [0x0, 'nanometer', 9, 0xd4e19f39],
51 [0x0, 'oblivion', 8, 0xdae9de77],
52 [0x0, 'panama', 6, 0x66b8979c],
53 [0x0, 'quest', 5, 0x4317f817],
54 [0x0, 'resource', 8, 0xbc91f416],
55 [0x0, 'secret', 6, 0x5ca2e8e5],
56 [0x0, 'test', 4, 0xd87f7e0c],
57 [0x0, 'ultimate', 8, 0x3fc79b0b],
58 [0x0, 'vector', 6, 0x1b6e485b],
59 [0x0, 'walrus', 6, 0xbe769b97],
60 [0x0, 'xeno', 4, 0xe7a06444],
61 [0x0, 'yelling', 7, 0xfe3944e5],
62 [0x0, 'zlib', 4, 0x73887d3a],
63 [0x0, '4BJD7PocN1VqX0jXVpWB', 20, 0xd487a5a1],
64 [0x0, 'F1rPWI7XvDs6nAIRx41l', 20, 0x61a0132e],
65 [0x0, 'ldhKlsVkPFOveXgkGtC2', 20, 0xdf02f76],
66 [0x0, '5KKnGOOrs8BvJ35iKTOS', 20, 0x579b2b0a],
67 [0x0, '0l1tw7GOcem06Ddu7yn4', 20, 0xf7d16e2d],
68 [0x0, 'MCr47CjPIn9R1IvE1Tm5', 20, 0x731788f5],
69 [0x0, 'UcixbzPKTIv0SvILHVdO', 20, 0x7112bb11],
70 [0x0, 'dGnAyAhRQDsWw0ESou24', 20, 0xf32a0dac],
71 [0x0, 'di0nvmY9UYMYDh0r45XT', 20, 0x625437bb],
72 [0x0, '2XKDwHfAhFsV0RhbqtvH', 20, 0x896930f9],
73 [0x0, 'ZhrANFIiIvRnqClIVyeD', 20, 0x8579a37],
74 [0x0, 'v7Q9ehzioTOVeDIZioT1', 20, 0x632aa8e0],
75 [0x0, 'Yod5hEeKcYqyhfXbhxj2', 20, 0xc829af29],
76 [0x0, 'GehSWY2ay4uUKhehXYb0', 20, 0x1b08b7e8],
77 [0x0, 'kwytJmq6UqpflV8Y8GoE', 20, 0x4e33b192],
78 [0x0, '70684206568419061514', 20, 0x59a179f0],
79 [0x0, '42015093765128581010', 20, 0xcd1013d7],
80 [0x0, '88214814356148806939', 20, 0xab927546],
81 [0x0, '43472694284527343838', 20, 0x11f3b20c],
82 [0x0, '49769333513942933689', 20, 0xd562d4ca],
83 [0x0, '54979784887993251199', 20, 0x233395f7],
84 [0x0, '58360544869206793220', 20, 0x2d167fd5],
85 [0x0, '27347953487840714234', 20, 0x8b5108ba],
86 [0x0, '07650690295365319082', 20, 0xc46b3cd8],
87 [0x0, '42655507906821911703', 20, 0xc10b2662],
88 [0x0, '29977409200786225655', 20, 0xc9a0f9d2],
89 [0x0, '85181542907229116674', 20, 0x9341357b],
90 [0x0, '87963594337989416799', 20, 0xf0424937],
91 [0x0, '21395988329504168551', 20, 0xd7c4c31f],
92 [0x0, '51991013580943379423', 20, 0xf11edcc4],
93 [0x0, '*]+@!);({_$;}[_},?{?;(_?,=-][@', 30, 0x40795df4],
94 [0x0, '_@:_).&(#.[:[{[:)$++-($_;@[)}+', 30, 0xdd61a631],
95 [0x0, '&[!,[$_==}+.]@!;*(+},[;:)$;)-@', 30, 0xca907a99],
96 [0x0, ']{.[.+?+[[=;[?}_#&;[=)__$$:+=_', 30, 0xf652deac],
97 [0x0, '-%.)=/[@].:.(:,()$;=%@-$?]{%+%', 30, 0xaf39a5a9],
98 [0x0, '+]#$(@&.=:,*];/.!]%/{:){:@(;)$', 30, 0x6bebb4cf],
99 [0x0, ')-._.:?[&:.=+}(*$/=!.${;(=$@!}', 30, 0x76430bac],
100 [0x0, ':(_*&%/[[}+,?#$&*+#[([*-/#;%(]', 30, 0x6c80c388],
101 [0x0, '{[#-;:$/{)(+[}#]/{&!%(@)%:@-$:', 30, 0xd54d977d],
102 [0x0, '_{$*,}(&,@.)):=!/%(&(,,-?$}}}!', 30, 0xe3966ad5],
103 [
104 0x0,
105 'e$98KNzqaV)Y:2X?]77].{gKRD4G5{mHZk,Z)SpU%L3FSgv!Wb8MLAFdi{+fp)c,@8m6v)yXg@]HBDFk?.4&}g5_udE*JHCiH=aL',
106 100,
107 0xe7c71db9,
108 ],
109 [
110 0x0,
111 'r*Fd}ef+5RJQ;+W=4jTR9)R*p!B;]Ed7tkrLi;88U7g@3v!5pk2X6D)vt,.@N8c]@yyEcKi[vwUu@.Ppm@C6%Mv*3Nw}Y,58_aH)',
112 100,
113 0xeaa52777,
114 ],
115 [
116 0x0,
117 'h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&',
118 100,
119 0xcd472048,
120 ],
121 [0x7a30360d, 'abacus', 6, 0xf8655a84],
122 [0x6fd767ee, 'backlog', 7, 0x1ed834b1],
123 [0xefeb7589, 'campfire', 8, 0x686cfca],
124 [0x61cf7e6b, 'delta', 5, 0x1554e4b1],
125 [0xdc712e2, 'executable', 10, 0x761b4254],
126 [0xad23c7fd, 'file', 4, 0x7abdd09b],
127 [0x85cb2317, 'greatest', 8, 0x4ba91c6b],
128 [0x9eed31b0, 'inverter', 8, 0xd5e78ba5],
129 [0xb94f34ca, 'jigsaw', 6, 0x23649109],
130 [0xab058a2, 'karate', 6, 0xc5591f41],
131 [0x5bff2b7a, 'landscape', 9, 0xf10eb644],
132 [0x605c9a5f, 'machine', 7, 0xbaa0a636],
133 [0x51bdeea5, 'nanometer', 9, 0x6af89afb],
134 [0x85c21c79, 'oblivion', 8, 0xecae222b],
135 [0x97216f56, 'panama', 6, 0x47dffac4],
136 [0x18444af2, 'quest', 5, 0x70c2fe36],
137 [0xbe6ce359, 'resource', 8, 0x1471d925],
138 [0x843071f1, 'secret', 6, 0x50c9a0db],
139 [0xf2480c60, 'ultimate', 8, 0xf973daf8],
140 [0x2d2feb3d, 'vector', 6, 0x344ac03d],
141 [0x7490310a, 'walrus', 6, 0x6d1408ef],
142 [0x97d247d4, 'xeno', 4, 0xe62670b5],
143 [0x93cf7599, 'yelling', 7, 0x1b36da38],
144 [0x73c84278, 'zlib', 4, 0x6432d127],
145 [0x228a87d1, '4BJD7PocN1VqX0jXVpWB', 20, 0x997107d0],
146 [0xa7a048d0, 'F1rPWI7XvDs6nAIRx41l', 20, 0xdc567274],
147 [0x1f0ded40, 'ldhKlsVkPFOveXgkGtC2', 20, 0xdcc63870],
148 [0xa804a62f, '5KKnGOOrs8BvJ35iKTOS', 20, 0x6926cffd],
149 [0x508fae6a, '0l1tw7GOcem06Ddu7yn4', 20, 0xb52b38bc],
150 [0xe5adaf4f, 'MCr47CjPIn9R1IvE1Tm5', 20, 0xf83b8178],
151 [0x67136a40, 'UcixbzPKTIv0SvILHVdO', 20, 0xc5213070],
152 [0xb00c4a10, 'dGnAyAhRQDsWw0ESou24', 20, 0xbc7648b0],
153 [0x2e0c84b5, 'di0nvmY9UYMYDh0r45XT', 20, 0xd8123a72],
154 [0x81238d44, '2XKDwHfAhFsV0RhbqtvH', 20, 0xd5ac5620],
155 [0xf853aa92, 'ZhrANFIiIvRnqClIVyeD', 20, 0xceae099d],
156 [0x5a692325, 'v7Q9ehzioTOVeDIZioT1', 20, 0xb07d2b24],
157 [0x3275b9f, 'Yod5hEeKcYqyhfXbhxj2', 20, 0x24ce91df],
158 [0x38371feb, 'GehSWY2ay4uUKhehXYb0', 20, 0x707b3b30],
159 [0xafc8bf62, 'kwytJmq6UqpflV8Y8GoE', 20, 0x16abc6a9],
160 [0x9b07db73, '70684206568419061514', 20, 0xae1fb7b7],
161 [0xe75b214, '42015093765128581010', 20, 0xd4eecd2d],
162 [0x72d0fe6f, '88214814356148806939', 20, 0x4660ec7],
163 [0xf857a4b1, '43472694284527343838', 20, 0xfd8afdf7],
164 [0x54b8e14, '49769333513942933689', 20, 0xc6d1b5f2],
165 [0xd6aa5616, '54979784887993251199', 20, 0x32476461],
166 [0x11e63098, '58360544869206793220', 20, 0xd917cf1a],
167 [0xbe92385, '27347953487840714234', 20, 0x4ad14a12],
168 [0x49511de0, '07650690295365319082', 20, 0xe37b5c6c],
169 [0x3db13bc1, '42655507906821911703', 20, 0x7cc497f1],
170 [0xbb899bea, '29977409200786225655', 20, 0x99781bb2],
171 [0xf6cd9436, '85181542907229116674', 20, 0x132256a1],
172 [0x9109e6c3, '87963594337989416799', 20, 0xbfdb2c83],
173 [0x75770fc, '21395988329504168551', 20, 0x8d9d1e81],
174 [0x69b1d19b, '51991013580943379423', 20, 0x7b6d4404],
175 [0xc6132975, '*]+@!);({_$;}[_},?{?;(_?,=-][@', 30, 0x8619f010],
176 [0xd58cb00c, '_@:_).&(#.[:[{[:)$++-($_;@[)}+', 30, 0x15746ac3],
177 [0xb63b8caa, '&[!,[$_==}+.]@!;*(+},[;:)$;)-@', 30, 0xaccf812f],
178 [0x8a45a2b8, ']{.[.+?+[[=;[?}_#&;[=)__$$:+=_', 30, 0x78af45de],
179 [0xcbe95b78, '-%.)=/[@].:.(:,()$;=%@-$?]{%+%', 30, 0x25b06b59],
180 [0x4ef8a54b, '+]#$(@&.=:,*];/.!]%/{:){:@(;)$', 30, 0x4ba0d08f],
181 [0x76ad267a, ')-._.:?[&:.=+}(*$/=!.${;(=$@!}', 30, 0xe26b6aac],
182 [0x569e613c, ':(_*&%/[[}+,?#$&*+#[([*-/#;%(]', 30, 0x7e2b0a66],
183 [0x36aa61da, '{[#-;:$/{)(+[}#]/{&!%(@)%:@-$:', 30, 0xb3430dc7],
184 [0xf67222df, '_{$*,}(&,@.)):=!/%(&(,,-?$}}}!', 30, 0x626c17a],
185 [
186 0x74b34fd3,
187 'e$98KNzqaV)Y:2X?]77].{gKRD4G5{mHZk,Z)SpU%L3FSgv!Wb8MLAFdi{+fp)c,@8m6v)yXg@]HBDFk?.4&}g5_udE*JHCiH=aL',
188 100,
189 0xccf98060,
190 ],
191 [
192 0x351fd770,
193 'r*Fd}ef+5RJQ;+W=4jTR9)R*p!B;]Ed7tkrLi;88U7g@3v!5pk2X6D)vt,.@N8c]@yyEcKi[vwUu@.Ppm@C6%Mv*3Nw}Y,58_aH)',
194 100,
195 0xd8b95312,
196 ],
197 [
198 0xc45aef77,
199 'h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&',
200 100,
201 0xbb1c9912,
202 ],
203 [
204 0xc45aef77,
205 'h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&' +
206 'h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&' +
207 'h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&' +
208 'h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&' +
209 'h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&' +
210 'h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&',
211 600,
212 0x888afa5b,
213 ],
214 ];
215 
216 for (const [crc, data, len, expected] of tests) {
217 if (data === 0) {
218 continue;
219 }
220 const buf = Buffer.from(data, 'utf8');
221 assert.strictEqual(buf.length, len);
222 assert.strictEqual(
223 zlib.crc32(buf, crc),
224 expected,
225 `crc32('${data}', ${crc}) in buffer is not ${expected}`
226 );
227 assert.strictEqual(
228 zlib.crc32(buf.toString(), crc),
229 expected,
230 `crc32('${data}', ${crc}) in string is not ${expected}`
231 );
232 if (crc === 0) {
233 assert.strictEqual(
234 zlib.crc32(buf),
235 expected,
236 `crc32('${data}') in buffer is not ${expected}`
237 );
238 assert.strictEqual(
239 zlib.crc32(buf.toString()),
240 expected,
241 `crc32('${data}') in string is not ${expected}`
242 );
243 }
244 }
245 
246 for (const invalid of [undefined, null, true, 1, () => {}, {}]) {
247 assert.throws(() => {
248 zlib.crc32(invalid);
249 }, new TypeError("Failed to execute 'crc32' on 'ZlibUtil': parameter 1 is not of type 'string or ArrayBuffer or ArrayBufferView'."));
250 }
251 
252 for (const invalid of [null, true, () => {}, {}]) {
253 assert.throws(
254 () => {
255 zlib.crc32('test', invalid);
256 },
257 { code: 'ERR_INVALID_ARG_TYPE' }
258 );
259 }
260 },
261};
262 
263export const constantsTest = {
264 test() {
265 assert.deepStrictEqual(Object.keys(zlib.constants).sort(), [
266 'BROTLI_DECODE',
267 'BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES',
268 'BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP',
269 'BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES',
270 'BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1',
271 'BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2',
272 'BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS',
273 'BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET',
274 'BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1',
275 'BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2',
276 'BROTLI_DECODER_ERROR_FORMAT_CL_SPACE',
277 'BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT',
278 'BROTLI_DECODER_ERROR_FORMAT_DICTIONARY',
279 'BROTLI_DECODER_ERROR_FORMAT_DISTANCE',
280 'BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE',
281 'BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE',
282 'BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE',
283 'BROTLI_DECODER_ERROR_FORMAT_PADDING_1',
284 'BROTLI_DECODER_ERROR_FORMAT_PADDING_2',
285 'BROTLI_DECODER_ERROR_FORMAT_RESERVED',
286 'BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET',
287 'BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME',
288 'BROTLI_DECODER_ERROR_FORMAT_TRANSFORM',
289 'BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS',
290 'BROTLI_DECODER_ERROR_INVALID_ARGUMENTS',
291 'BROTLI_DECODER_ERROR_UNREACHABLE',
292 'BROTLI_DECODER_NEEDS_MORE_INPUT',
293 'BROTLI_DECODER_NEEDS_MORE_OUTPUT',
294 'BROTLI_DECODER_NO_ERROR',
295 'BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION',
296 'BROTLI_DECODER_PARAM_LARGE_WINDOW',
297 'BROTLI_DECODER_RESULT_ERROR',
298 'BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT',
299 'BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT',
300 'BROTLI_DECODER_RESULT_SUCCESS',
301 'BROTLI_DECODER_SUCCESS',
302 'BROTLI_DEFAULT_MODE',
303 'BROTLI_DEFAULT_QUALITY',
304 'BROTLI_DEFAULT_WINDOW',
305 'BROTLI_ENCODE',
306 'BROTLI_LARGE_MAX_WINDOW_BITS',
307 'BROTLI_MAX_INPUT_BLOCK_BITS',
308 'BROTLI_MAX_QUALITY',
309 'BROTLI_MAX_WINDOW_BITS',
310 'BROTLI_MIN_INPUT_BLOCK_BITS',
311 'BROTLI_MIN_QUALITY',
312 'BROTLI_MIN_WINDOW_BITS',
313 'BROTLI_MODE_FONT',
314 'BROTLI_MODE_GENERIC',
315 'BROTLI_MODE_TEXT',
316 'BROTLI_OPERATION_EMIT_METADATA',
317 'BROTLI_OPERATION_FINISH',
318 'BROTLI_OPERATION_FLUSH',
319 'BROTLI_OPERATION_PROCESS',
320 'BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING',
321 'BROTLI_PARAM_LARGE_WINDOW',
322 'BROTLI_PARAM_LGBLOCK',
323 'BROTLI_PARAM_LGWIN',
324 'BROTLI_PARAM_MODE',
325 'BROTLI_PARAM_NDIRECT',
326 'BROTLI_PARAM_NPOSTFIX',
327 'BROTLI_PARAM_QUALITY',
328 'BROTLI_PARAM_SIZE_HINT',
329 'DEFLATE',
330 'DEFLATERAW',
331 'GUNZIP',
332 'GZIP',
333 'INFLATE',
334 'INFLATERAW',
335 'UNZIP',
336 'ZLIB_VERNUM',
337 'ZSTD_CLEVEL_DEFAULT',
338 'ZSTD_COMPRESS',
339 'ZSTD_DECODE',
340 'ZSTD_DECOMPRESS',
341 'ZSTD_ENCODE',
342 'ZSTD_btlazy2',
343 'ZSTD_btopt',
344 'ZSTD_btultra',
345 'ZSTD_btultra2',
346 'ZSTD_c_chainLog',
347 'ZSTD_c_checksumFlag',
348 'ZSTD_c_compressionLevel',
349 'ZSTD_c_contentSizeFlag',
350 'ZSTD_c_dictIDFlag',
351 'ZSTD_c_enableLongDistanceMatching',
352 'ZSTD_c_hashLog',
353 'ZSTD_c_jobSize',
354 'ZSTD_c_ldmBucketSizeLog',
355 'ZSTD_c_ldmHashLog',
356 'ZSTD_c_ldmHashRateLog',
357 'ZSTD_c_ldmMinMatch',
358 'ZSTD_c_minMatch',
359 'ZSTD_c_nbWorkers',
360 'ZSTD_c_overlapLog',
361 'ZSTD_c_searchLog',
362 'ZSTD_c_strategy',
363 'ZSTD_c_targetLength',
364 'ZSTD_c_windowLog',
365 'ZSTD_d_windowLogMax',
366 'ZSTD_dfast',
367 'ZSTD_e_continue',
368 'ZSTD_e_end',
369 'ZSTD_e_flush',
370 'ZSTD_error_GENERIC',
371 'ZSTD_error_checksum_wrong',
372 'ZSTD_error_corruption_detected',
373 'ZSTD_error_dictionaryCreation_failed',
374 'ZSTD_error_dictionary_corrupted',
375 'ZSTD_error_dictionary_wrong',
376 'ZSTD_error_dstBuffer_null',
377 'ZSTD_error_dstSize_tooSmall',
378 'ZSTD_error_frameParameter_unsupported',
379 'ZSTD_error_frameParameter_windowTooLarge',
380 'ZSTD_error_init_missing',
381 'ZSTD_error_literals_headerWrong',
382 'ZSTD_error_maxSymbolValue_tooLarge',
383 'ZSTD_error_maxSymbolValue_tooSmall',
384 'ZSTD_error_memory_allocation',
385 'ZSTD_error_noForwardProgress_destFull',
386 'ZSTD_error_noForwardProgress_inputEmpty',
387 'ZSTD_error_no_error',
388 'ZSTD_error_parameter_combination_unsupported',
389 'ZSTD_error_parameter_outOfBound',
390 'ZSTD_error_parameter_unsupported',
391 'ZSTD_error_prefix_unknown',
392 'ZSTD_error_srcSize_wrong',
393 'ZSTD_error_stabilityCondition_notRespected',
394 'ZSTD_error_stage_wrong',
395 'ZSTD_error_tableLog_tooLarge',
396 'ZSTD_error_version_unsupported',
397 'ZSTD_error_workSpace_tooSmall',
398 'ZSTD_fast',
399 'ZSTD_greedy',
400 'ZSTD_lazy',
401 'ZSTD_lazy2',
402 'Z_BEST_COMPRESSION',
403 'Z_BEST_SPEED',
404 'Z_BLOCK',
405 'Z_BUF_ERROR',
406 'Z_DATA_ERROR',
407 'Z_DEFAULT_CHUNK',
408 'Z_DEFAULT_COMPRESSION',
409 'Z_DEFAULT_LEVEL',
410 'Z_DEFAULT_MEMLEVEL',
411 'Z_DEFAULT_STRATEGY',
412 'Z_DEFAULT_WINDOWBITS',
413 'Z_ERRNO',
414 'Z_FILTERED',
415 'Z_FINISH',
416 'Z_FIXED',
417 'Z_FULL_FLUSH',
418 'Z_HUFFMAN_ONLY',
419 'Z_MAX_CHUNK',
420 'Z_MAX_LEVEL',
421 'Z_MAX_MEMLEVEL',
422 'Z_MAX_WINDOWBITS',
423 'Z_MEM_ERROR',
424 'Z_MIN_CHUNK',
425 'Z_MIN_LEVEL',
426 'Z_MIN_MEMLEVEL',
427 'Z_MIN_WINDOWBITS',
428 'Z_NEED_DICT',
429 'Z_NO_COMPRESSION',
430 'Z_NO_FLUSH',
431 'Z_OK',
432 'Z_PARTIAL_FLUSH',
433 'Z_RLE',
434 'Z_STREAM_END',
435 'Z_STREAM_ERROR',
436 'Z_SYNC_FLUSH',
437 'Z_VERSION_ERROR',
438 ]);
439 },
440};
441 
442// This test makes sure constants can be accessed from the zlib module directly
443// This is supported by NodeJS, but is deprecated.
444export const constantsDirectlyUnderZlibTest = {
445 test() {
446 assert.deepStrictEqual(zlib.Z_NEED_DICT, 2);
447 assert.deepStrictEqual(zlib.Z_OK, 0);
448 },
449};
450 
451// Tests are taken from:
452// https://github.com/nodejs/node/blob/561bc87c7607208f0d3db6dcd9231efeb48cfe2f/test/parallel/test-zlib-zero-windowBits.js
453export const testZeroWindowBits = {
454 test() {
455 // windowBits is a special case in zlib. On the compression side, 0 is invalid.
456 // On the decompression side, it indicates that zlib should use the value from
457 // the header of the compressed stream.
458 {
459 const inflate = zlib.createInflate({ windowBits: 0 });
460 assert(inflate instanceof zlib.Inflate);
461 }
462 
463 {
464 const gunzip = zlib.createGunzip({ windowBits: 0 });
465 assert(gunzip instanceof zlib.Gunzip);
466 }
467 
468 {
469 const unzip = zlib.createUnzip({ windowBits: 0 });
470 assert(unzip instanceof zlib.Unzip);
471 }
472 
473 assert.throws(() => zlib.createGzip({ windowBits: 0 }), {
474 code: 'ERR_OUT_OF_RANGE',
475 name: 'RangeError',
476 message:
477 'The value of "options.windowBits" is out of range. ' +
478 'It must be >= 9 and <= 15. Received 0',
479 });
480 },
481};
482 
483// Tests are taken from:
484// https://github.com/nodejs/node/blob/561bc87c7607208f0d3db6dcd9231efeb48cfe2f/test/parallel/test-zlib-create-raw.js
485export const testCreateRaw = {
486 test() {
487 {
488 const inflateRaw = zlib.createInflateRaw();
489 assert(inflateRaw instanceof zlib.InflateRaw);
490 }
491 
492 {
493 const deflateRaw = zlib.createDeflateRaw();
494 assert(deflateRaw instanceof zlib.DeflateRaw);
495 }
496 },
497};
498 
499// Tests are taken from:
500// https://github.com/nodejs/node/blob/561bc87c7607208f0d3db6dcd9231efeb48cfe2f/test/parallel/test-zlib-deflate-constructors.js
501export const testDeflateConstructors = {
502 test() {
503 assert(new zlib.Deflate() instanceof zlib.Deflate);
504 assert(new zlib.DeflateRaw() instanceof zlib.DeflateRaw);
505 
506 // Throws if `options.chunkSize` is invalid
507 assert.throws(() => new zlib.Deflate({ chunkSize: 'test' }), {
508 code: 'ERR_INVALID_ARG_TYPE',
509 name: 'TypeError',
510 });
511 
512 assert.throws(() => new zlib.Deflate({ chunkSize: -Infinity }), {
513 code: 'ERR_OUT_OF_RANGE',
514 name: 'RangeError',
515 });
516 
517 assert.throws(() => new zlib.Deflate({ chunkSize: 0 }), {
518 code: 'ERR_OUT_OF_RANGE',
519 name: 'RangeError',
520 });
521 
522 // Throws if `options.windowBits` is invalid
523 assert.throws(() => new zlib.Deflate({ windowBits: 'test' }), {
524 code: 'ERR_INVALID_ARG_TYPE',
525 name: 'TypeError',
526 });
527 
528 assert.throws(() => new zlib.Deflate({ windowBits: -Infinity }), {
529 code: 'ERR_OUT_OF_RANGE',
530 name: 'RangeError',
531 });
532 
533 assert.throws(() => new zlib.Deflate({ windowBits: Infinity }), {
534 code: 'ERR_OUT_OF_RANGE',
535 name: 'RangeError',
536 });
537 
538 assert.throws(() => new zlib.Deflate({ windowBits: 0 }), {
539 code: 'ERR_OUT_OF_RANGE',
540 name: 'RangeError',
541 });
542 
543 // Throws if `options.level` is invalid
544 assert.throws(() => new zlib.Deflate({ level: 'test' }), {
545 code: 'ERR_INVALID_ARG_TYPE',
546 name: 'TypeError',
547 });
548 
549 assert.throws(() => new zlib.Deflate({ level: -Infinity }), {
550 code: 'ERR_OUT_OF_RANGE',
551 name: 'RangeError',
552 });
553 
554 assert.throws(() => new zlib.Deflate({ level: Infinity }), {
555 code: 'ERR_OUT_OF_RANGE',
556 name: 'RangeError',
557 });
558 
559 assert.throws(() => new zlib.Deflate({ level: -2 }), {
560 code: 'ERR_OUT_OF_RANGE',
561 name: 'RangeError',
562 });
563 
564 // Throws if `level` invalid in `Deflate.prototype.params()`
565 assert.throws(() => new zlib.Deflate().params('test'), {
566 code: 'ERR_INVALID_ARG_TYPE',
567 name: 'TypeError',
568 });
569 
570 assert.throws(() => new zlib.Deflate().params(-Infinity), {
571 code: 'ERR_OUT_OF_RANGE',
572 name: 'RangeError',
573 });
574 
575 assert.throws(() => new zlib.Deflate().params(Infinity), {
576 code: 'ERR_OUT_OF_RANGE',
577 name: 'RangeError',
578 });
579 
580 assert.throws(() => new zlib.Deflate().params(-2), {
581 code: 'ERR_OUT_OF_RANGE',
582 name: 'RangeError',
583 });
584 
585 // Throws if options.memLevel is invalid
586 assert.throws(() => new zlib.Deflate({ memLevel: 'test' }), {
587 code: 'ERR_INVALID_ARG_TYPE',
588 name: 'TypeError',
589 });
590 
591 assert.throws(() => new zlib.Deflate({ memLevel: -Infinity }), {
592 code: 'ERR_OUT_OF_RANGE',
593 name: 'RangeError',
594 });
595 
596 assert.throws(() => new zlib.Deflate({ memLevel: Infinity }), {
597 code: 'ERR_OUT_OF_RANGE',
598 name: 'RangeError',
599 });
600 
601 assert.throws(() => new zlib.Deflate({ memLevel: -2 }), {
602 code: 'ERR_OUT_OF_RANGE',
603 name: 'RangeError',
604 });
605 
606 // Does not throw if opts.strategy is valid
607 new zlib.Deflate({ strategy: zlib.constants.Z_FILTERED });
608 new zlib.Deflate({ strategy: zlib.constants.Z_HUFFMAN_ONLY });
609 new zlib.Deflate({ strategy: zlib.constants.Z_RLE });
610 new zlib.Deflate({ strategy: zlib.constants.Z_FIXED });
611 new zlib.Deflate({ strategy: zlib.constants.Z_DEFAULT_STRATEGY });
612 
613 // Throws if options.strategy is invalid
614 assert.throws(() => new zlib.Deflate({ strategy: 'test' }), {
615 code: 'ERR_INVALID_ARG_TYPE',
616 name: 'TypeError',
617 });
618 
619 assert.throws(() => new zlib.Deflate({ strategy: -Infinity }), {
620 code: 'ERR_OUT_OF_RANGE',
621 name: 'RangeError',
622 });
623 
624 assert.throws(() => new zlib.Deflate({ strategy: Infinity }), {
625 code: 'ERR_OUT_OF_RANGE',
626 name: 'RangeError',
627 });
628 
629 assert.throws(() => new zlib.Deflate({ strategy: -2 }), {
630 code: 'ERR_OUT_OF_RANGE',
631 name: 'RangeError',
632 });
633 
634 // Throws TypeError if `strategy` is invalid in `Deflate.prototype.params()`
635 assert.throws(() => new zlib.Deflate().params(0, 'test'), {
636 code: 'ERR_INVALID_ARG_TYPE',
637 name: 'TypeError',
638 });
639 
640 assert.throws(() => new zlib.Deflate().params(0, -Infinity), {
641 code: 'ERR_OUT_OF_RANGE',
642 name: 'RangeError',
643 });
644 
645 assert.throws(() => new zlib.Deflate().params(0, Infinity), {
646 code: 'ERR_OUT_OF_RANGE',
647 name: 'RangeError',
648 });
649 
650 assert.throws(() => new zlib.Deflate().params(0, -2), {
651 code: 'ERR_OUT_OF_RANGE',
652 name: 'RangeError',
653 });
654 
655 // Throws if opts.dictionary is not a Buffer
656 assert.throws(() => new zlib.Deflate({ dictionary: 'not a buffer' }), {
657 code: 'ERR_INVALID_ARG_TYPE',
658 name: 'TypeError',
659 });
660 },
661};
662 
663// Tests are taken from:
664// https://github.com/nodejs/node/blob/561bc87c7607208f0d3db6dcd9231efeb48cfe2f/test/parallel/test-zlib-failed-init.js
665export const testFailedInit = {
666 test() {
667 assert.throws(() => zlib.createGzip({ chunkSize: 0 }), {
668 code: 'ERR_OUT_OF_RANGE',
669 name: 'RangeError',
670 });
671 
672 assert.throws(() => zlib.createGzip({ windowBits: 0 }), {
673 code: 'ERR_OUT_OF_RANGE',
674 name: 'RangeError',
675 });
676 
677 assert.throws(() => zlib.createGzip({ memLevel: 0 }), {
678 code: 'ERR_OUT_OF_RANGE',
679 name: 'RangeError',
680 });
681 
682 {
683 const stream = zlib.createGzip({ level: NaN });
684 assert.strictEqual(stream._level, zlib.constants.Z_DEFAULT_COMPRESSION);
685 }
686 
687 {
688 const stream = zlib.createGzip({ strategy: NaN });
689 assert.strictEqual(stream._strategy, zlib.constants.Z_DEFAULT_STRATEGY);
690 }
691 },
692};
693 
694// Tests are taken from:
695// https://github.com/nodejs/node/blob/561bc87c7607208f0d3db6dcd9231efeb48cfe2f/test/parallel/test-zlib-destroy.js
696export const zlibDestroyTest = {
697 async test() {
698 const promises = [];
699 // Verify that the zlib transform does clean up
700 // the handle when calling destroy.
701 {
702 const ts = zlib.createGzip();
703 ts.destroy();
704 assert.strictEqual(ts._handle, null);
705 
706 const { promise, resolve, reject } = Promise.withResolvers();
707 promises.push(promise);
708 ts.on('error', reject);
709 ts.on('close', () => {
710 ts.close(() => {
711 resolve();
712 });
713 });
714 }
715 
716 {
717 // Ensure 'error' is only emitted once.
718 const decompress = zlib.createGunzip(15);
719 const { promise, resolve, reject: _reject } = Promise.withResolvers();
720 promises.push(promise);
721 let errorCount = 0;
722 decompress.on('error', (err) => {
723 errorCount++;
724 decompress.close();
725 assert.strictEqual(errorCount, 1, 'Error should only be emitted once');
726 resolve();
727 });
728 
729 decompress.write('something invalid');
730 decompress.destroy(new Error('asd'));
731 }
732 
733 await Promise.all(promises);
734 },
735};
736 
737// Tests are taken from:
738// https://github.com/nodejs/node/blob/561bc87c7607208f0d3db6dcd9231efeb48cfe2f/test/parallel/test-zlib-close-after-error.js
739export const closeAfterError = {
740 async test() {
741 const decompress = zlib.createGunzip(15);
742 const { promise, resolve } = Promise.withResolvers();
743 let errorHasBeenCalled = false;
744 
745 decompress.on('error', () => {
746 errorHasBeenCalled = true;
747 assert.strictEqual(decompress._closed, true);
748 decompress.close();
749 });
750 
751 assert.strictEqual(decompress._closed, false);
752 decompress.write('something invalid');
753 decompress.on('close', resolve);
754 
755 await promise;
756 
757 assert(errorHasBeenCalled, 'Error handler should have been called');
758 },
759};
760 
761// Tests are taken from:
762// https://github.com/nodejs/node/blob/561bc87c7607208f0d3db6dcd9231efeb48cfe2f/test/parallel/test-zlib-write-after-close.js
763export const writeAfterClose = {
764 async test() {
765 const { promise, resolve } = Promise.withResolvers();
766 let close = mock.fn();
767 zlib.gzip('hello', function (err, out) {
768 const unzip = zlib.createGunzip();
769 unzip.close(close);
770 unzip.write('asd', (err) => {
771 assert.strictEqual(err.code, 'ERR_STREAM_DESTROYED');
772 assert.strictEqual(err.name, 'Error');
773 resolve();
774 });
775 });
776 await promise;
777 assert.strictEqual(close.mock.callCount(), 1);
778 },
779};
780 
781// Tests are taken from:
782// https://github.com/nodejs/node/blob/9edf4a0856681a7665bd9dcf2ca7cac252784b98/test/parallel/test-zlib-bytes-read.js
783export const testZlibBytesRead = {
784 async test() {
785 const expectStr = 'abcdefghijklmnopqrstuvwxyz'.repeat(2);
786 const expectBuf = Buffer.from(expectStr);
787 
788 function createWriter(target, buffer) {
789 const writer = { size: 0 };
790 const write = () => {
791 target.write(Buffer.from([buffer[writer.size++]]), () => {
792 if (writer.size < buffer.length) {
793 target.flush(write);
794 } else {
795 target.end();
796 }
797 });
798 };
799 write();
800 return writer;
801 }
802 
803 // This test is simplified a lot because of test runner limitations.
804 for (const method of [
805 'createGzip',
806 'createDeflate',
807 'createDeflateRaw',
808 'createBrotliCompress',
809 ]) {
810 assert(method in zlib, `${method} is not available in "node:zlib"`);
811 const { promise, resolve, reject } = Promise.withResolvers();
812 let compData = Buffer.alloc(0);
813 const comp = zlib[method]();
814 const compWriter = createWriter(comp, expectBuf);
815 comp.on('data', function (d) {
816 compData = Buffer.concat([compData, d]);
817 assert.strictEqual(
818 this.bytesWritten,
819 compWriter.size,
820 `Should get write size on ${method} data.`
821 );
822 });
823 comp.on('error', reject);
824 comp.on('end', function () {
825 assert.strictEqual(
826 this.bytesWritten,
827 compWriter.size,
828 `Should get write size on ${method} end.`
829 );
830 assert.strictEqual(
831 this.bytesWritten,
832 expectStr.length,
833 `Should get data size on ${method} end.`
834 );
835 
836 resolve();
837 });
838 
839 await promise;
840 }
841 },
842};
843 
844// Tests are taken from:
845// https://github.com/nodejs/node/blob/3a71ccf6c473357e89be61b26739fd9139dce4db/test/parallel/test-zlib-const.js
846export const zlibConst = {
847 test() {
848 assert.strictEqual(zlib.constants.Z_OK, 0, 'Expected Z_OK to be 0');
849 assert.throws(() => {
850 zlib.constants.Z_OK = 1;
851 }, /Cannot assign to read only property/);
852 assert.strictEqual(zlib.constants.Z_OK, 0, 'Z_OK should be immutable');
853 assert.strictEqual(
854 zlib.codes.Z_OK,
855 0,
856 `Expected Z_OK to be 0; got ${zlib.codes.Z_OK}`
857 );
858 assert.throws(() => {
859 zlib.codes.Z_OK = 1;
860 }, /Cannot assign to read only property/);
861 assert.strictEqual(zlib.codes.Z_OK, 0, 'Z_OK should be immutable');
862 assert(Object.isFrozen(zlib.codes), 'Expected zlib.codes to be frozen');
863 
864 assert.deepStrictEqual(zlib.codes, {
865 '-1': 'Z_ERRNO',
866 '-2': 'Z_STREAM_ERROR',
867 '-3': 'Z_DATA_ERROR',
868 '-4': 'Z_MEM_ERROR',
869 '-5': 'Z_BUF_ERROR',
870 '-6': 'Z_VERSION_ERROR',
871 0: 'Z_OK',
872 1: 'Z_STREAM_END',
873 2: 'Z_NEED_DICT',
874 Z_BUF_ERROR: -5,
875 Z_DATA_ERROR: -3,
876 Z_ERRNO: -1,
877 Z_MEM_ERROR: -4,
878 Z_NEED_DICT: 2,
879 Z_OK: 0,
880 Z_STREAM_END: 1,
881 Z_STREAM_ERROR: -2,
882 Z_VERSION_ERROR: -6,
883 });
884 },
885};
886 
887// Tests are taken from:
888// https://github.com/nodejs/node/blob/3a71ccf6c473357e89be61b26739fd9139dce4db/test/parallel/test-zlib-object-write.js
889 
890export const zlibObjectWrite = {
891 async test() {
892 const { promise, resolve, reject } = Promise.withResolvers();
893 const gunzip = new zlib.Gunzip({ objectMode: true });
894 gunzip.on('error', reject);
895 assert.throws(
896 () => {
897 gunzip.write({});
898 },
899 {
900 name: 'TypeError',
901 code: 'ERR_INVALID_ARG_TYPE',
902 }
903 );
904 gunzip.on('close', resolve);
905 gunzip.close();
906 await promise;
907 },
908};
909 
910// Tests are taken from:
911// https://github.com/nodejs/node/blob/3a71ccf6c473357e89be61b26739fd9139dce4db/test/parallel/test-zlib-zero-byte.js
912export const zlibZeroByte = {
913 async test() {
914 for (const Compressor of [zlib.Gzip, zlib.BrotliCompress]) {
915 const { promise, resolve, reject } = Promise.withResolvers();
916 let endCalled = false;
917 const gz = new Compressor();
918 const emptyBuffer = Buffer.alloc(0);
919 let received = 0;
920 gz.on('data', function (c) {
921 received += c.length;
922 });
923 
924 gz.on('end', function () {
925 const expected = Compressor === zlib.Gzip ? 20 : 1;
926 assert.strictEqual(
927 received,
928 expected,
929 `${received}, ${expected}, ${Compressor.name}`
930 );
931 endCalled = true;
932 });
933 gz.on('error', reject);
934 gz.on('finish', resolve);
935 gz.write(emptyBuffer);
936 gz.end();
937 
938 await promise;
939 assert(endCalled, 'End should have been called');
940 }
941 },
942};
943 
944// Tests are taken from:
945// https://github.com/nodejs/node/blob/431ac161e65698152de197703fb30c89da2b6686/test/parallel/test-zlib-dictionary-fail.js
946export const zlibDictionaryFail = {
947 async test() {
948 // String "test" encoded with dictionary "dict".
949 const input = Buffer.from([0x78, 0xbb, 0x04, 0x09, 0x01, 0xa5]);
950 
951 {
952 const { promise, resolve } = Promise.withResolvers();
953 const stream = zlib.createInflate();
954 
955 stream.on('error', function (err) {
956 assert.match(err.message, /Missing dictionary/);
957 resolve();
958 });
959 
960 stream.write(input);
961 await promise;
962 }
963 
964 {
965 const { promise, resolve } = Promise.withResolvers();
966 const stream = zlib.createInflate({ dictionary: Buffer.from('fail') });
967 
968 stream.on('error', function (err) {
969 assert.match(err.message, /Bad dictionary/);
970 resolve();
971 });
972 
973 stream.write(input);
974 await promise;
975 }
976 
977 {
978 const { promise, resolve } = Promise.withResolvers();
979 const stream = zlib.createInflateRaw({ dictionary: Buffer.from('fail') });
980 
981 stream.on('error', function (err) {
982 // It's not possible to separate invalid dict and invalid data when using
983 // the raw format
984 assert.match(
985 err.message,
986 /(invalid|Operation-Ending-Supplemental Code is 0x12)/
987 );
988 resolve();
989 });
990 
991 stream.write(input);
992 await promise;
993 }
994 },
995};
996 
997// Tests are taken from:
998// https://github.com/nodejs/node/blob/431ac161e65698152de197703fb30c89da2b6686/test/parallel/test-zlib-close-in-ondata.js
999export const zlibCloseInOnData = {
1000 async test() {
1001 const { promise, resolve } = Promise.withResolvers();
1002 const ts = zlib.createGzip();
1003 const buf = Buffer.alloc(1024 * 1024 * 20);
1004 
1005 ts.on('data', function () {
1006 ts.close();
1007 resolve();
1008 });
1009 ts.end(buf);
1010 await promise;
1011 },
1012};
1013 
1014// Tests are taken from:
1015// https://github.com/nodejs/node/blob/431ac161e65698152de197703fb30c89da2b6686/test/parallel/test-zlib-flush-flags.js
1016export const zlibFlushFlags = {
1017 test() {
1018 zlib.createGzip({ flush: zlib.constants.Z_SYNC_FLUSH });
1019 
1020 assert.throws(() => zlib.createGzip({ flush: 'foobar' }), {
1021 code: 'ERR_INVALID_ARG_TYPE',
1022 name: 'TypeError',
1023 message:
1024 'The "options.flush" property must be of type number. ' +
1025 "Received type string ('foobar')",
1026 });
1027 
1028 assert.throws(() => zlib.createGzip({ flush: 10000 }), {
1029 code: 'ERR_OUT_OF_RANGE',
1030 name: 'RangeError',
1031 message:
1032 'The value of "options.flush" is out of range. It must ' +
1033 'be >= 0 and <= 5. Received 10000',
1034 });
1035 
1036 zlib.createGzip({ finishFlush: zlib.constants.Z_SYNC_FLUSH });
1037 
1038 assert.throws(() => zlib.createGzip({ finishFlush: 'foobar' }), {
1039 code: 'ERR_INVALID_ARG_TYPE',
1040 name: 'TypeError',
1041 message:
1042 'The "options.finishFlush" property must be of type number. ' +
1043 "Received type string ('foobar')",
1044 });
1045 
1046 assert.throws(() => zlib.createGzip({ finishFlush: 10000 }), {
1047 code: 'ERR_OUT_OF_RANGE',
1048 name: 'RangeError',
1049 message:
1050 'The value of "options.finishFlush" is out of range. It must ' +
1051 'be >= 0 and <= 5. Received 10000',
1052 });
1053 },
1054};
1055 
1056// Tests are taken from:
1057// https://github.com/nodejs/node/blob/431ac161e65698152de197703fb30c89da2b6686/test/parallel/test-zlib-reset-before-write.js
1058export const zlibResetBeforeWrite = {
1059 async test() {
1060 // Tests that zlib streams support .reset() and .params()
1061 // before the first write. That is important to ensure that
1062 // lazy init of zlib native library handles these cases.
1063 
1064 for (const fn of [
1065 (z, cb) => {
1066 z.reset();
1067 cb();
1068 },
1069 (z, cb) => z.params(0, zlib.constants.Z_DEFAULT_STRATEGY, cb),
1070 ]) {
1071 const { promise, resolve, reject } = Promise.withResolvers();
1072 const deflate = zlib.createDeflate();
1073 const inflate = zlib.createInflate();
1074 
1075 deflate.pipe(inflate);
1076 
1077 const output = [];
1078 inflate
1079 .on('error', reject)
1080 .on('data', (chunk) => output.push(chunk))
1081 .on('end', resolve);
1082 
1083 fn(deflate, () => {
1084 fn(inflate, () => {
1085 deflate.write('abc');
1086 deflate.end();
1087 });
1088 });
1089 
1090 await promise;
1091 
1092 assert.strictEqual(Buffer.concat(output).toString(), 'abc');
1093 }
1094 },
1095};
1096 
1097// Tests are taken from:
1098// https://github.com/nodejs/node/blob/6bf7b6e342f97cf48319e0bc251200fabe132c21/test/parallel/test-zlib-invalid-input.js
1099export const zlibInvalidInput = {
1100 async test() {
1101 const nonStringInputs = [1, true, { a: 1 }, ['a']];
1102 
1103 // zlib.Unzip classes need to get valid data, or else they'll throw.
1104 const unzips = [
1105 new zlib.Unzip(),
1106 new zlib.Gunzip(),
1107 new zlib.Inflate(),
1108 new zlib.InflateRaw(),
1109 new zlib.BrotliDecompress(),
1110 ];
1111 
1112 for (const input of nonStringInputs) {
1113 assert.throws(
1114 () => {
1115 zlib.gunzip(input);
1116 },
1117 {
1118 name: 'TypeError',
1119 }
1120 );
1121 }
1122 
1123 for (const uz of unzips) {
1124 const { promise, resolve, reject } = Promise.withResolvers();
1125 uz.on('error', resolve);
1126 uz.on('end', reject);
1127 
1128 // This will trigger error event
1129 uz.write('this is not valid compressed data.');
1130 await promise;
1131 }
1132 },
1133};
1134 
1135// Tests are taken from:
1136// https://github.com/nodejs/node/blob/5e6aab0ecad6394e538e06357d6e16e155951a8b/test/parallel/test-zlib-unzip-one-byte-chunks.js
1137export const zlibUnzipOneByteChunks = {
1138 async test() {
1139 const { promise, resolve, reject } = Promise.withResolvers();
1140 const data = Buffer.concat([zlib.gzipSync('abc'), zlib.gzipSync('def')]);
1141 
1142 const resultBuffers = [];
1143 
1144 const unzip = zlib
1145 .createUnzip()
1146 .on('error', reject)
1147 .on('data', (data) => resultBuffers.push(data))
1148 .on('finish', resolve);
1149 
1150 for (let i = 0; i < data.length; i++) {
1151 // Write each single byte individually.
1152 unzip.write(Buffer.from([data[i]]));
1153 }
1154 
1155 unzip.end();
1156 await promise;
1157 assert.strictEqual(Buffer.concat(resultBuffers).toString(), 'abcdef');
1158 },
1159};
1160 
1161// Tests are taken from:
1162// https://github.com/nodejs/node/blob/4f14eb15454b9f6ae7f0145947debd2c79a2a84f/test/parallel/test-zlib-truncated.js
1163export const zlibTruncated = {
1164 async test() {
1165 const inputString =
1166 'ΩΩLorem ipsum dolor sit amet, consectetur adipiscing eli' +
1167 't. Morbi faucibus, purus at gravida dictum, libero arcu ' +
1168 'convallis lacus, in commodo libero metus eu nisi. Nullam' +
1169 ' commodo, neque nec porta placerat, nisi est fermentum a' +
1170 'ugue, vitae gravida tellus sapien sit amet tellus. Aenea' +
1171 'n non diam orci. Proin quis elit turpis. Suspendisse non' +
1172 ' diam ipsum. Suspendisse nec ullamcorper odio. Vestibulu' +
1173 'm arcu mi, sodales non suscipit id, ultrices ut massa. S' +
1174 'ed ac sem sit amet arcu malesuada fermentum. Nunc sed. ';
1175 
1176 const errMessage = /unexpected end of file/;
1177 
1178 const cases = [
1179 { comp: 'gzip', decomp: 'gunzip', decompSync: 'gunzipSync' },
1180 { comp: 'gzip', decomp: 'unzip', decompSync: 'unzipSync' },
1181 { comp: 'deflate', decomp: 'inflate', decompSync: 'inflateSync' },
1182 {
1183 comp: 'deflateRaw',
1184 decomp: 'inflateRaw',
1185 decompSync: 'inflateRawSync',
1186 },
1187 ];
1188 for (const methods of cases) {
1189 const { promise, resolve } = Promise.withResolvers();
1190 zlib[methods.comp](inputString, async function (err, compressed) {
1191 assert.ifError(err);
1192 const truncated = compressed.slice(0, compressed.length / 2);
1193 const toUTF8 = (buffer) => buffer.toString('utf-8');
1194 
1195 // sync sanity
1196 const decompressed = zlib[methods.decompSync](compressed);
1197 assert.strictEqual(toUTF8(decompressed), inputString);
1198 
1199 // async sanity
1200 {
1201 const { promise, resolve } = Promise.withResolvers();
1202 zlib[methods.decomp](compressed, function (err, result) {
1203 assert.ifError(err);
1204 assert.strictEqual(toUTF8(result), inputString);
1205 resolve();
1206 });
1207 
1208 await promise;
1209 }
1210 
1211 // Sync truncated input test
1212 assert.throws(function () {
1213 zlib[methods.decompSync](truncated);
1214 }, errMessage);
1215 
1216 // Async truncated input test
1217 {
1218 const { promise, resolve } = Promise.withResolvers();
1219 zlib[methods.decomp](truncated, function (err) {
1220 assert.match(err.message, errMessage);
1221 resolve();
1222 });
1223 
1224 await promise;
1225 }
1226 
1227 const syncFlushOpt = { finishFlush: zlib.constants.Z_SYNC_FLUSH };
1228 
1229 // Sync truncated input test, finishFlush = Z_SYNC_FLUSH
1230 const result = toUTF8(
1231 zlib[methods.decompSync](truncated, syncFlushOpt)
1232 );
1233 assert.strictEqual(result, inputString.slice(0, result.length));
1234 
1235 // Async truncated input test, finishFlush = Z_SYNC_FLUSH
1236 {
1237 const { promise, resolve } = Promise.withResolvers();
1238 zlib[methods.decomp](
1239 truncated,
1240 syncFlushOpt,
1241 function (err, decompressed) {
1242 assert.ifError(err);
1243 const result = toUTF8(decompressed);
1244 assert.strictEqual(result, inputString.slice(0, result.length));
1245 resolve();
1246 }
1247 );
1248 await promise;
1249 }
1250 
1251 resolve();
1252 });
1253 
1254 await promise;
1255 }
1256 },
1257};
1258 
1259// Tests are taken from:
1260// https://github.com/nodejs/node/blob/beabcec41ca456e7e895e276acbc5f2d93db032f/test/parallel/test-zlib-from-concatenated-gzip.js
1261export const zlibFromConcatenatedGzip = {
1262 async test() {
1263 const abc = 'abc';
1264 const def = 'def';
1265 
1266 const abcEncoded = zlib.gzipSync(abc);
1267 const defEncoded = zlib.gzipSync(def);
1268 
1269 const data = Buffer.concat([abcEncoded, defEncoded]);
1270 
1271 assert.strictEqual(zlib.gunzipSync(data).toString(), abc + def);
1272 
1273 {
1274 const { promise, resolve } = Promise.withResolvers();
1275 zlib.gunzip(data, (err, result) => {
1276 assert.ifError(err);
1277 assert.strictEqual(result.toString(), abc + def);
1278 resolve();
1279 });
1280 
1281 await promise;
1282 }
1283 
1284 {
1285 const { promise, resolve } = Promise.withResolvers();
1286 zlib.unzip(data, (err, result) => {
1287 assert.ifError(err);
1288 assert.strictEqual(result.toString(), abc + def);
1289 resolve();
1290 });
1291 
1292 await promise;
1293 }
1294 
1295 // Multi-member support does not apply to zlib inflate/deflate.
1296 {
1297 const { promise, resolve } = Promise.withResolvers();
1298 zlib.unzip(
1299 Buffer.concat([zlib.deflateSync('abc'), zlib.deflateSync('def')]),
1300 (err, result) => {
1301 assert.ifError(err);
1302 assert.strictEqual(result.toString(), abc);
1303 resolve();
1304 }
1305 );
1306 
1307 await promise;
1308 }
1309 
1310 {
1311 // Files that have the "right" magic bytes for starting a new gzip member
1312 // in the middle of themselves, even if they are part of a single
1313 // regularly compressed member
1314 const pmmDataZlib = Buffer.from(
1315 'eJztwTEBAAAAwqD1T+1vBqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
1316 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
1317 'AAAAAAAAAAAAAAAAAAAAAAAAAAAIAz+w4AAQ==',
1318 'base64'
1319 );
1320 const pmmDataGz = Buffer.from(
1321 'H4sIAMyK8lYCA+3BMQEAAADCoPVP7WENoAAAAAAAAAAAAAAAAAAAAAAAH4sAAAAAAAAAAAAAAAAA' +
1322 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
1323 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABuGn4Inv/6AQA=',
1324 'base64'
1325 );
1326 const pmmExpected = zlib.inflateSync(pmmDataZlib);
1327 const pmmResultBuffers = [];
1328 const { promise, resolve, reject } = Promise.withResolvers();
1329 
1330 Readable.from([pmmDataGz])
1331 .pipe(zlib.createGunzip())
1332 .on('error', reject)
1333 .on('data', (data) => pmmResultBuffers.push(data))
1334 .on('finish', resolve);
1335 
1336 await promise;
1337 // Result should match original random garbage
1338 assert.deepStrictEqual(Buffer.concat(pmmResultBuffers), pmmExpected);
1339 }
1340 
1341 // Test that the next gzip member can wrap around the input buffer boundary
1342 for (const offset of [0, 1, 2, 3, 4, defEncoded.length]) {
1343 const { promise, resolve, reject } = Promise.withResolvers();
1344 const resultBuffers = [];
1345 
1346 const unzip = zlib
1347 .createGunzip()
1348 .on('error', reject)
1349 .on('data', (data) => resultBuffers.push(data))
1350 .on('finish', resolve);
1351 
1352 // First write: write "abc" + the first bytes of "def"
1353 unzip.write(Buffer.concat([abcEncoded, defEncoded.slice(0, offset)]));
1354 
1355 // Write remaining bytes of "def"
1356 unzip.end(defEncoded.slice(offset));
1357 
1358 await promise;
1359 
1360 assert.strictEqual(
1361 Buffer.concat(resultBuffers).toString(),
1362 'abcdef',
1363 `result should match original input (offset = ${offset})`
1364 );
1365 }
1366 },
1367};
1368 
1369// Test taken from:
1370// https://github.com/nodejs/node/blob/fc02b88f89f8d5abf5ee4414a1026444c18d77b3/test/parallel/test-zlib-not-string-or-buffer.js
1371export const zlibNotStringOrBuffer = {
1372 test() {
1373 for (const input of [
1374 undefined,
1375 null,
1376 true,
1377 false,
1378 0,
1379 1,
1380 [1, 2, 3],
1381 { foo: 'bar' },
1382 ]) {
1383 assert.throws(
1384 () => zlib.deflateSync(input),
1385 // TODO(soon): Use same error code as NodeJS
1386 {
1387 name: 'TypeError',
1388 }
1389 );
1390 }
1391 },
1392};
1393 
1394// Test taken from:
1395// https://github.com/nodejs/node/blob/fc02b88f89f8d5abf5ee4414a1026444c18d77b3/test/parallel/test-zlib-from-gzip-with-trailing-garbage.js
1396export const zlibFromGzipWithTrailingGarbage = {
1397 async test() {
1398 // Should ignore trailing null-bytes
1399 let data = Buffer.concat([
1400 zlib.gzipSync('abc'),
1401 zlib.gzipSync('def'),
1402 Buffer.alloc(10),
1403 ]);
1404 
1405 assert.strictEqual(zlib.gunzipSync(data).toString(), 'abcdef');
1406 
1407 {
1408 const { promise, resolve } = Promise.withResolvers();
1409 
1410 zlib.gunzip(data, (err, result) => {
1411 assert.ifError(err);
1412 assert.strictEqual(
1413 result.toString(),
1414 'abcdef',
1415 `result '${result.toString()}' should match original string`
1416 );
1417 resolve();
1418 });
1419 
1420 await promise;
1421 }
1422 
1423 // If the trailing garbage happens to look like a gzip header, it should
1424 // throw an error.
1425 data = Buffer.concat([
1426 zlib.gzipSync('abc'),
1427 zlib.gzipSync('def'),
1428 Buffer.from([0x1f, 0x8b, 0xff, 0xff]),
1429 Buffer.alloc(10),
1430 ]);
1431 
1432 assert.throws(
1433 () => zlib.gunzipSync(data),
1434 /^Error: unknown compression method$/
1435 );
1436 
1437 {
1438 const { promise, resolve } = Promise.withResolvers();
1439 zlib.gunzip(data, (err, result) => {
1440 // TODO(soon): use same error code as NodeJS
1441 // TODO(soon): Do our messages have a redundant "Error: " word?
1442 assert.strictEqual(err.name, 'Error');
1443 assert.match(err.message, /unknown compression method/);
1444 assert.strictEqual(result, undefined);
1445 resolve();
1446 });
1447 
1448 await promise;
1449 }
1450 
1451 // In this case the trailing junk is too short to be a gzip segment
1452 // So we ignore it and decompression succeeds.
1453 data = Buffer.concat([
1454 zlib.gzipSync('abc'),
1455 zlib.gzipSync('def'),
1456 Buffer.from([0x1f, 0x8b, 0xff, 0xff]),
1457 ]);
1458 
1459 assert.throws(
1460 () => zlib.gunzipSync(data),
1461 /^Error: unknown compression method$/
1462 );
1463 
1464 {
1465 const { promise, resolve } = Promise.withResolvers();
1466 zlib.gunzip(data, (err, result) => {
1467 // TODO(soon): Use same error code as NodeJS
1468 // TODO(soon): Do our messages have a redundant "Error: " word?
1469 assert.strictEqual(err.name, 'Error');
1470 assert.match(err.message, /unknown compression method/);
1471 assert.strictEqual(result, undefined);
1472 resolve();
1473 });
1474 
1475 await promise;
1476 }
1477 },
1478};
1479 
1480// Test taken from
1481// https://github.com/nodejs/node/blob/fc02b88f89f8d5abf5ee4414a1026444c18d77b3/test/parallel/test-zlib-from-string.js
1482export const zlibFromString = {
1483 async test() {
1484 const inputString =
1485 'ΩΩLorem ipsum dolor sit amet, consectetur adipiscing eli' +
1486 't. Morbi faucibus, purus at gravida dictum, libero arcu ' +
1487 'convallis lacus, in commodo libero metus eu nisi. Nullam' +
1488 ' commodo, neque nec porta placerat, nisi est fermentum a' +
1489 'ugue, vitae gravida tellus sapien sit amet tellus. Aenea' +
1490 'n non diam orci. Proin quis elit turpis. Suspendisse non' +
1491 ' diam ipsum. Suspendisse nec ullamcorper odio. Vestibulu' +
1492 'm arcu mi, sodales non suscipit id, ultrices ut massa. S' +
1493 'ed ac sem sit amet arcu malesuada fermentum. Nunc sed. ';
1494 const expectedBase64Deflate =
1495 'eJxdUUtOQzEMvMoc4OndgT0gJCT2buJWlpI4jePeqZfpmX' +
1496 'AKLRKbLOzx/HK73q6vOrhCunlF1qIDJhNUeW5I2ozT5OkD' +
1497 'lKWLJWkncJG5403HQXAkT3Jw29B9uIEmToMukglZ0vS6oc' +
1498 'iBh4JG8sV4oVLEUCitK2kxq1WzPnChHDzsaGKy491LofoA' +
1499 'bWh8do43oeuYhB5EPCjcLjzYJo48KrfQBvnJecNFJvHT1+' +
1500 'RSQsGoC7dn2t/xjhduTA1NWyQIZR0pbHwMDatnD+crPqKS' +
1501 'qGPHp1vnlsWM/07ubf7bheF7kqSj84Bm0R1fYTfaK8vqqq' +
1502 'fKBtNMhe3OZh6N95CTvMX5HJJi4xOVzCgUOIMSLH7wmeOH' +
1503 'aFE4RdpnGavKtrB5xzfO/Ll9';
1504 const expectedBase64Gzip =
1505 'H4sIAAAAAAAAA11RS05DMQy8yhzg6d2BPSAkJPZu4laWkjiN4' +
1506 '96pl+mZcAotEpss7PH8crverq86uEK6eUXWogMmE1R5bkjajN' +
1507 'Pk6QOUpYslaSdwkbnjTcdBcCRPcnDb0H24gSZOgy6SCVnS9Lq' +
1508 'hyIGHgkbyxXihUsRQKK0raTGrVbM+cKEcPOxoYrLj3Uuh+gBt' +
1509 'aHx2jjeh65iEHkQ8KNwuPNgmjjwqt9AG+cl5w0Um8dPX5FJCw' +
1510 'agLt2fa3/GOF25MDU1bJAhlHSlsfAwNq2cP5ys+opKoY8enW+' +
1511 'eWxYz/Tu5t/tuF4XuSpKPzgGbRHV9hN9ory+qqp8oG00yF7c5' +
1512 'mHo33kJO8xfkckmLjE5XMKBQ4gxIsfvCZ44doUThF2mcZq8q2' +
1513 'sHnHNzRtagj5AQAA';
1514 
1515 {
1516 const { promise, resolve } = Promise.withResolvers();
1517 zlib.deflate(inputString, (err, buffer) => {
1518 zlib.inflate(buffer, (err, inflated) => {
1519 assert.strictEqual(inflated.toString(), inputString);
1520 resolve();
1521 });
1522 });
1523 await promise;
1524 }
1525 
1526 {
1527 const { promise, resolve } = Promise.withResolvers();
1528 zlib.gzip(inputString, (err, buffer) => {
1529 assert.ifError(err);
1530 // Can't actually guarantee that we'll get exactly the same
1531 // deflated bytes when we compress a string, since the header
1532 // depends on stuff other than the input string itself.
1533 // However, decrypting it should definitely yield the same
1534 // result that we're expecting, and this should match what we get
1535 // from inflating the known valid deflate data.
1536 zlib.gunzip(buffer, (err, gunzipped) => {
1537 assert.ifError(err);
1538 assert.strictEqual(gunzipped.toString(), inputString);
1539 resolve();
1540 });
1541 });
1542 await promise;
1543 }
1544 
1545 let buffer = Buffer.from(expectedBase64Deflate, 'base64');
1546 {
1547 const { promise, resolve } = Promise.withResolvers();
1548 zlib.unzip(buffer, (err, buffer) => {
1549 assert.ifError(err);
1550 assert.strictEqual(buffer.toString(), inputString);
1551 resolve();
1552 });
1553 
1554 await promise;
1555 }
1556 
1557 buffer = Buffer.from(expectedBase64Gzip, 'base64');
1558 
1559 {
1560 const { promise, resolve } = Promise.withResolvers();
1561 zlib.unzip(buffer, (err, buffer) => {
1562 assert.ifError(err);
1563 assert.strictEqual(buffer.toString(), inputString);
1564 resolve();
1565 });
1566 await promise;
1567 }
1568 },
1569};
1570 
1571// Test taken from
1572// https://github.com/nodejs/node/blob/fc02b88f89f8d5abf5ee4414a1026444c18d77b3/test/parallel/test-zlib-empty-buffer.js
1573export const zlibEmptyBuffer = {
1574 async test() {
1575 const emptyBuffer = Buffer.alloc(0);
1576 
1577 for (const [compress, decompress, method] of [
1578 [zlib.deflateRawSync, zlib.inflateRawSync, 'raw sync'],
1579 [zlib.deflateSync, zlib.inflateSync, 'deflate sync'],
1580 [zlib.gzipSync, zlib.gunzipSync, 'gzip sync'],
1581 [zlib.brotliCompressSync, zlib.brotliDecompressSync, 'br sync'],
1582 [promisify(zlib.deflateRaw), promisify(zlib.inflateRaw), 'raw'],
1583 [promisify(zlib.deflate), promisify(zlib.inflate), 'deflate'],
1584 [promisify(zlib.gzip), promisify(zlib.gunzip), 'gzip'],
1585 [promisify(zlib.brotliCompress), promisify(zlib.brotliDecompress), 'br'],
1586 ]) {
1587 const compressed = await compress(emptyBuffer);
1588 const decompressed = await decompress(compressed);
1589 assert.deepStrictEqual(
1590 emptyBuffer,
1591 decompressed,
1592 `Expected ${inspect(compressed)} to match ${inspect(decompressed)} ` +
1593 `to match for ${method}`
1594 );
1595 }
1596 },
1597};
1598 
1599// Test taken from:
1600// https://github.com/nodejs/node/blob/d75e253c506310ea6728329981beb3284fa431b5/test/parallel/test-zlib-flush.js
1601export const zlibFlush = {
1602 async test() {
1603 const opts = { level: 0 };
1604 const deflater = zlib.createDeflate(opts);
1605 
1606 const chunk = Buffer.from('/9j/4AAQSkZJRgABAQEASA==', 'base64');
1607 const expectedNone = Buffer.from([0x78, 0x01]);
1608 const blkhdr = Buffer.from([0x00, 0x10, 0x00, 0xef, 0xff]);
1609 const adler32 = Buffer.from([0x00, 0x00, 0x00, 0xff, 0xff]);
1610 const expectedFull = Buffer.concat([blkhdr, chunk, adler32]);
1611 let actualNone;
1612 let actualFull;
1613 
1614 const { promise, resolve } = Promise.withResolvers();
1615 deflater.write(chunk, function () {
1616 deflater.flush(zlib.constants.Z_NO_FLUSH, function () {
1617 actualNone = deflater.read();
1618 deflater.flush(function () {
1619 const bufs = [];
1620 let buf;
1621 while ((buf = deflater.read()) !== null) bufs.push(buf);
1622 actualFull = Buffer.concat(bufs);
1623 
1624 resolve();
1625 });
1626 });
1627 });
1628 
1629 await promise;
1630 assert.deepStrictEqual(actualNone, expectedNone);
1631 assert.deepStrictEqual(actualFull, expectedFull);
1632 },
1633};
1634 
1635// Test taken from:
1636// https://github.com/nodejs/node/blob/9bdf2ee1d184e7ec5c690319e068894ed324b595/test/parallel/test-zlib-dictionary.js
1637export const zlibDictionary = {
1638 async test() {
1639 const spdyDict = Buffer.from(
1640 [
1641 'optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-',
1642 'languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi',
1643 'f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser',
1644 '-agent10010120020120220320420520630030130230330430530630740040140240340440',
1645 '5406407408409410411412413414415416417500501502503504505accept-rangesageeta',
1646 'glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic',
1647 'ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran',
1648 'sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati',
1649 'oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo',
1650 'ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe',
1651 'pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic',
1652 'ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1',
1653 '.1statusversionurl\0',
1654 ].join('')
1655 );
1656 
1657 const input = [
1658 'HTTP/1.1 200 Ok',
1659 'Server: node.js',
1660 'Content-Length: 0',
1661 '',
1662 ].join('\r\n');
1663 
1664 // basicDictionaryTest
1665 {
1666 let { promise, resolve, reject } = Promise.withResolvers();
1667 let output = '';
1668 const deflate = zlib.createDeflate({ dictionary: spdyDict });
1669 const inflate = zlib.createInflate({ dictionary: spdyDict });
1670 inflate.setEncoding('utf-8');
1671 
1672 deflate
1673 .on('data', function (chunk) {
1674 inflate.write(chunk);
1675 })
1676 .on('error', reject)
1677 .on('end', function () {
1678 inflate.end();
1679 });
1680 
1681 inflate
1682 .on('error', reject)
1683 .on('end', resolve)
1684 .on('data', function (chunk) {
1685 output += chunk;
1686 });
1687 
1688 deflate.write(input);
1689 deflate.end();
1690 await promise;
1691 assert.strictEqual(input, output);
1692 }
1693 
1694 // deflateResetDictionaryTest
1695 {
1696 let { promise, resolve, reject } = Promise.withResolvers();
1697 let doneReset = false;
1698 let output = '';
1699 const deflate = zlib.createDeflate({ dictionary: spdyDict });
1700 const inflate = zlib.createInflate({ dictionary: spdyDict });
1701 inflate.setEncoding('utf-8');
1702 
1703 deflate
1704 .on('data', function (chunk) {
1705 if (doneReset) inflate.write(chunk);
1706 })
1707 .on('error', reject)
1708 .on('end', function () {
1709 inflate.end();
1710 });
1711 
1712 inflate
1713 .on('data', function (chunk) {
1714 output += chunk;
1715 })
1716 .on('error', reject)
1717 .on('end', resolve);
1718 
1719 deflate.write(input);
1720 deflate.flush(function () {
1721 deflate.reset();
1722 doneReset = true;
1723 deflate.write(input);
1724 deflate.end();
1725 });
1726 
1727 await promise;
1728 assert.strictEqual(input, output);
1729 }
1730 
1731 // rawDictionaryTest
1732 {
1733 let { promise, resolve, reject } = Promise.withResolvers();
1734 let output = '';
1735 const deflate = zlib.createDeflateRaw({ dictionary: spdyDict });
1736 const inflate = zlib.createInflateRaw({ dictionary: spdyDict });
1737 inflate.setEncoding('utf-8');
1738 
1739 deflate
1740 .on('data', function (chunk) {
1741 inflate.write(chunk);
1742 })
1743 .on('error', reject)
1744 .on('end', function () {
1745 inflate.end();
1746 });
1747 inflate
1748 .on('data', function (chunk) {
1749 output += chunk;
1750 })
1751 .on('error', reject)
1752 .on('end', resolve);
1753 
1754 deflate.write(input);
1755 deflate.end();
1756 
1757 await promise;
1758 assert.strictEqual(input, output);
1759 }
1760 
1761 // deflateRawResetDictionaryTest
1762 {
1763 let { promise, resolve, reject } = Promise.withResolvers();
1764 let doneReset = false;
1765 let output = '';
1766 const deflate = zlib.createDeflateRaw({ dictionary: spdyDict });
1767 const inflate = zlib.createInflateRaw({ dictionary: spdyDict });
1768 inflate.setEncoding('utf-8');
1769 
1770 deflate
1771 .on('data', function (chunk) {
1772 if (doneReset) inflate.write(chunk);
1773 })
1774 .on('error', reject)
1775 .on('end', function () {
1776 inflate.end();
1777 });
1778 
1779 inflate
1780 .on('data', function (chunk) {
1781 output += chunk;
1782 })
1783 .on('error', reject)
1784 .on('end', resolve);
1785 
1786 deflate.write(input);
1787 deflate.flush(function () {
1788 deflate.reset();
1789 doneReset = true;
1790 deflate.write(input);
1791 deflate.end();
1792 });
1793 
1794 await promise;
1795 assert.strictEqual(input, output);
1796 }
1797 },
1798};
1799 
1800// Test taken from
1801// https://github.com/nodejs/node/blob/ef6b9ffc8dfc7b2a395c864d2729a0ce1be9ef18/test/parallel/test-zlib-close-after-write.js
1802export const closeAfterWrite = {
1803 async test() {
1804 const { promise, resolve } = Promise.withResolvers();
1805 zlib.gzip('hello', (err, out) => {
1806 assert.ifError(err);
1807 
1808 const unzip = zlib.createGunzip();
1809 unzip.write(out);
1810 unzip.close(resolve);
1811 });
1812 await promise;
1813 },
1814};
1815 
1816export const inflateSyncTest = {
1817 test() {
1818 const BIG_DATA = 'horse'.repeat(50_000) + 'cow'.repeat(49_000);
1819 assert.strictEqual(
1820 zlib.inflateSync(zlib.deflateSync(BIG_DATA)).toString(),
1821 BIG_DATA
1822 );
1823 
1824 assert.throws(
1825 () => zlib.inflateSync('garbage data'),
1826 new Error('incorrect header check')
1827 );
1828 
1829 assert.strictEqual(
1830 zlib
1831 .inflateSync(Buffer.from('OE9LyixKUUiCEQAmfgUk', 'base64'), {
1832 windowBits: 11,
1833 level: 4,
1834 })
1835 .toString(),
1836 'bird bird bird'
1837 );
1838 },
1839};
1840 
1841export const zipBombTest = {
1842 test() {
1843 // 225 bytes (raw)
1844 const ZLIB_BOMB_3 =
1845 'eNqruPX2jqHeUkaJtov/25xEzoho9fL6aF70yPBZvUBsqZPmzHO+F253euVbWScs28QQ2LG' +
1846 'CpdBc8ef84mkfpubvs6n/Z/9vrk9b4oy4ffG2ujp8DAwMB074/p97traX8fCt43fPvbMDCh' +
1847 'mUtZ/2/rw58MHbhNLblkCBhC96ZuZ1Z+xY5vn3P5/LDBRxy3/6NTF7G+udupj/d4r5gSISe' +
1848 '6sPAikGD0EeINkgBuZkQDgSyJxRmVGZUZlRmVGZURlCMpZRcVE/bjGdi/fzr+O/n/P32XWD' +
1849 'nyxJaZvuAwDXRDs+';
1850 
1851 // 1799 bytes
1852 const zlib_bomb_2 = zlib.inflateSync(Buffer.from(ZLIB_BOMB_3, 'base64'));
1853 
1854 // ~ 1MB
1855 const zlib_bomb_1 = zlib.inflateSync(zlib_bomb_2);
1856 
1857 // Would be 1 GB, if we let it
1858 assert.throws(
1859 () => zlib.inflateSync(zlib_bomb_1),
1860 new RangeError('Memory limit exceeded')
1861 );
1862 },
1863};
1864 
1865export const deflateSyncTest = {
1866 test() {
1867 function maskOsId(buf) {
1868 // Clear the OS ID byte in gzip, which varies based on the platform used to run the tests
1869 return buf.fill(0x0, 9, 10);
1870 }
1871 
1872 assert.strictEqual(
1873 zlib
1874 .deflateSync('bird bird bird', { windowBits: 11, level: 4 })
1875 .toString('base64'),
1876 'OE9LyixKUUiCEQAmfgUk'
1877 );
1878 
1879 assert.deepStrictEqual(
1880 maskOsId(
1881 zlib.gzipSync('water, water, everywhere, nor any drop to drink')
1882 ).toString('base64'),
1883 'H4sIAAAAAAAAACtPLEkt0lEoh1CpZalFleUZqUWpOgp5+UUKiXmVCilF+QUKJfkKKUWZedkAqpLyPC8AAAA='
1884 );
1885 },
1886};
1887 
1888// Tests are taken from:
1889// https://github.com/nodejs/node/blob/5949e169bd886fcc965172f671671b47ac07d2e2/test/parallel/test-zlib-premature-end.js
1890export const prematureEnd = {
1891 async test() {
1892 const input = '0123456789'.repeat(4);
1893 
1894 for (const [compress, decompressor] of [
1895 [zlib.deflateRawSync, zlib.createInflateRaw],
1896 [zlib.deflateSync, zlib.createInflate],
1897 [zlib.brotliCompressSync, zlib.createBrotliDecompress],
1898 ]) {
1899 const compressed = compress(input);
1900 const trailingData = Buffer.from('not valid compressed data');
1901 
1902 for (const variant of [
1903 (stream) => {
1904 stream.end(compressed);
1905 },
1906 (stream) => {
1907 stream.write(compressed);
1908 stream.write(trailingData);
1909 },
1910 (stream) => {
1911 stream.write(compressed);
1912 stream.end(trailingData);
1913 },
1914 (stream) => {
1915 stream.write(Buffer.concat([compressed, trailingData]));
1916 },
1917 (stream) => {
1918 stream.end(Buffer.concat([compressed, trailingData]));
1919 },
1920 ]) {
1921 let output = '';
1922 const { promise, resolve, reject } = Promise.withResolvers();
1923 const stream = decompressor();
1924 stream.setEncoding('utf8');
1925 stream
1926 .on('data', (chunk) => (output += chunk))
1927 .on('end', () => {
1928 assert.strictEqual(output, input);
1929 assert.strictEqual(stream.bytesWritten, compressed.length);
1930 resolve();
1931 })
1932 .on('error', reject);
1933 variant(stream);
1934 await promise;
1935 }
1936 }
1937 },
1938};
1939 
1940// Tests are taken from:
1941// https://github.com/nodejs/node/blob/5949e169bd886fcc965172f671671b47ac07d2e2/test/parallel/test-zlib-write-after-flush.js
1942export const writeAfterFlush = {
1943 async test() {
1944 for (const [createCompress, createDecompress] of [
1945 [zlib.createGzip, zlib.createGunzip],
1946 [zlib.createBrotliCompress, zlib.createBrotliDecompress],
1947 ]) {
1948 const { promise, resolve, reject } = Promise.withResolvers();
1949 const gzip = createCompress();
1950 const gunz = createDecompress();
1951 
1952 gzip.pipe(gunz);
1953 
1954 let output = '';
1955 const input = 'A line of data\n';
1956 gunz.setEncoding('utf8');
1957 gunz
1958 .on('error', reject)
1959 .on('data', (c) => (output += c))
1960 .on('end', resolve);
1961 
1962 // Make sure that flush/write doesn't trigger an assert failure
1963 gzip.flush();
1964 gzip.write(input);
1965 gzip.end();
1966 gunz.read(0);
1967 await promise;
1968 assert.strictEqual(output, input);
1969 }
1970 },
1971};
1972 
1973// Tests are taken from:
1974// https://github.com/nodejs/node/blob/5949e169bd886fcc965172f671671b47ac07d2e2/test/parallel/test-zlib-destroy-pipe.js
1975export const destroyPipe = {
1976 async test() {
1977 const ts = zlib.createGzip();
1978 const { promise, resolve } = Promise.withResolvers();
1979 
1980 const ws = new Writable({
1981 write: (chunk, enc, cb) => {
1982 queueMicrotask(cb);
1983 ts.destroy();
1984 resolve();
1985 },
1986 });
1987 
1988 const buf = Buffer.allocUnsafe(1024 * 1024 * 20);
1989 ts.end(buf);
1990 ts.pipe(ws);
1991 await promise;
1992 },
1993};
1994 
1995// Tests are taken from:
1996// https://github.com/nodejs/node/blob/5949e169bd886fcc965172f671671b47ac07d2e2/test/parallel/test-zlib-write-after-end.js
1997export const writeAfterEnd = {
1998 async test() {
1999 const { promise, resolve } = Promise.withResolvers();
2000 const data = zlib.deflateRawSync('Welcome');
2001 const inflate = zlib.createInflateRaw();
2002 const writeCallback = mock.fn();
2003 inflate.resume();
2004 inflate.write(data, writeCallback);
2005 inflate.write(Buffer.from([0x00]), writeCallback);
2006 inflate.write(Buffer.from([0x00]), writeCallback);
2007 inflate.flush(resolve);
2008 await promise;
2009 assert.strictEqual(writeCallback.mock.callCount(), 3);
2010 },
2011};
2012 
2013// Tests are taken from:
2014// https://github.com/nodejs/node/blob/5949e169bd886fcc965172f671671b47ac07d2e2/test/parallel/test-zlib-convenience-methods.js
2015export const convenienceMethods = {
2016 async test() {
2017 // Must be a multiple of 4 characters in total to test all ArrayBufferView
2018 // types.
2019 const expectStr = 'blah'.repeat(8);
2020 const expectBuf = Buffer.from(expectStr);
2021 
2022 const opts = {
2023 level: 9,
2024 chunkSize: 1024,
2025 };
2026 
2027 const optsInfo = {
2028 info: true,
2029 };
2030 
2031 for (const [type, expect] of [
2032 ['string', expectStr],
2033 ['Buffer', expectBuf],
2034 ]) {
2035 for (const method of [
2036 ['gzip', 'gunzip', 'Gzip', 'Gunzip'],
2037 ['gzip', 'unzip', 'Gzip', 'Unzip'],
2038 ['deflate', 'inflate', 'Deflate', 'Inflate'],
2039 ['deflateRaw', 'inflateRaw', 'DeflateRaw', 'InflateRaw'],
2040 [
2041 'brotliCompress',
2042 'brotliDecompress',
2043 'BrotliCompress',
2044 'BrotliDecompress',
2045 ],
2046 ]) {
2047 {
2048 const { promise, resolve } = Promise.withResolvers();
2049 zlib[method[0]](expect, opts, (err, result) => {
2050 assert.ifError(err);
2051 zlib[method[1]](result, opts, (err, result) => {
2052 assert.ifError(err);
2053 assert.strictEqual(
2054 result.toString(),
2055 expectStr,
2056 `Should get original string after ${method[0]}/` +
2057 `${method[1]} ${type} with options.`
2058 );
2059 resolve();
2060 });
2061 });
2062 await promise;
2063 }
2064 
2065 {
2066 const { promise, resolve } = Promise.withResolvers();
2067 zlib[method[0]](expect, (err, result) => {
2068 assert.ifError(err);
2069 zlib[method[1]](result, (err, result) => {
2070 assert.ifError(err);
2071 assert.strictEqual(
2072 result.toString(),
2073 expectStr,
2074 `Should get original string after ${method[0]}/` +
2075 `${method[1]} ${type} without options.`
2076 );
2077 resolve();
2078 });
2079 });
2080 await promise;
2081 }
2082 
2083 {
2084 const { promise, resolve } = Promise.withResolvers();
2085 zlib[method[0]](expect, optsInfo, (err, result) => {
2086 assert.ifError(err);
2087 
2088 const compressed = result.buffer;
2089 zlib[method[1]](compressed, optsInfo, (err, result) => {
2090 assert.ifError(err);
2091 assert.strictEqual(
2092 result.buffer.toString(),
2093 expectStr,
2094 `Should get original string after ${method[0]}/` +
2095 `${method[1]} ${type} with info option.`
2096 );
2097 resolve();
2098 });
2099 });
2100 await promise;
2101 }
2102 
2103 {
2104 const compressed = zlib[`${method[0]}Sync`](expect, opts);
2105 const decompressed = zlib[`${method[1]}Sync`](compressed, opts);
2106 assert.strictEqual(
2107 decompressed.toString(),
2108 expectStr,
2109 `Should get original string after ${method[0]}Sync/` +
2110 `${method[1]}Sync ${type} with options.`
2111 );
2112 }
2113 
2114 {
2115 const compressed = zlib[`${method[0]}Sync`](expect);
2116 const decompressed = zlib[`${method[1]}Sync`](compressed);
2117 assert.strictEqual(
2118 decompressed.toString(),
2119 expectStr,
2120 `Should get original string after ${method[0]}Sync/` +
2121 `${method[1]}Sync ${type} without options.`
2122 );
2123 }
2124 
2125 {
2126 const compressed = zlib[`${method[0]}Sync`](expect, optsInfo);
2127 const decompressed = zlib[`${method[1]}Sync`](
2128 compressed.buffer,
2129 optsInfo
2130 );
2131 assert.strictEqual(
2132 decompressed.buffer.toString(),
2133 expectStr,
2134 `Should get original string after ${method[0]}Sync/` +
2135 `${method[1]}Sync ${type} without options.`
2136 );
2137 assert.ok(
2138 decompressed.engine instanceof zlib[method[3]],
2139 `Should get engine ${method[3]} after ${method[0]} ` +
2140 `${type} with info option.`
2141 );
2142 }
2143 }
2144 }
2145 
2146 assert.throws(() => zlib.gzip('abc'), {
2147 code: 'ERR_INVALID_ARG_TYPE',
2148 name: 'TypeError',
2149 message:
2150 'The "callback" argument must be of type function. ' +
2151 'Received undefined',
2152 });
2153 },
2154};
2155 
2156// Test taken from
2157// https://github.com/nodejs/node/blob/2bd6a57b7b934afcaf437a90e2abebcb79c13acf/test/parallel/test-zlib-brotli-from-string.js
2158export const brotliFromString = {
2159 async test() {
2160 const inputString =
2161 'ΩΩLorem ipsum dolor sit amet, consectetur adipiscing eli' +
2162 't. Morbi faucibus, purus at gravida dictum, libero arcu ' +
2163 'convallis lacus, in commodo libero metus eu nisi. Nullam' +
2164 ' commodo, neque nec porta placerat, nisi est fermentum a' +
2165 'ugue, vitae gravida tellus sapien sit amet tellus. Aenea' +
2166 'n non diam orci. Proin quis elit turpis. Suspendisse non' +
2167 ' diam ipsum. Suspendisse nec ullamcorper odio. Vestibulu' +
2168 'm arcu mi, sodales non suscipit id, ultrices ut massa. S' +
2169 'ed ac sem sit amet arcu malesuada fermentum. Nunc sed. ';
2170 const compressedString =
2171 'G/gBQBwHdky2aHV5KK9Snf05//1pPdmNw/7232fnIm1IB' +
2172 'K1AA8RsN8OB8Nb7Lpgk3UWWUlzQXZyHQeBBbXMTQXC1j7' +
2173 'wg3LJs9LqOGHRH2bj/a2iCTLLx8hBOyTqgoVuD1e+Qqdn' +
2174 'f1rkUNyrWq6LtOhWgxP3QUwdhKGdZm3rJWaDDBV7+pDk1' +
2175 'MIkrmjp4ma2xVi5MsgJScA3tP1I7mXeby6MELozrwoBQD' +
2176 'mVTnEAicZNj4lkGqntJe2qSnGyeMmcFgraK94vCg/4iLu' +
2177 'Tw5RhKhnVY++dZ6niUBmRqIutsjf5TzwF5iAg8a9UkjF5' +
2178 '2eZ0tB2vo6v8SqVfNMkBmmhxr0NT9LkYF69aEjlYzj7IE' +
2179 'KmEUQf1HBogRYhFIt4ymRNEgHAIzOyNEsQM=';
2180 
2181 {
2182 const { promise, resolve } = Promise.withResolvers();
2183 
2184 zlib.brotliCompress(inputString, (err, buffer) => {
2185 assert.ifError(err);
2186 assert(inputString.length > buffer.length);
2187 
2188 zlib.brotliDecompress(buffer, (err, buffer) => {
2189 assert.ifError(err);
2190 assert.strictEqual(buffer.toString(), inputString);
2191 resolve();
2192 });
2193 });
2194 await promise;
2195 }
2196 
2197 {
2198 const { promise, resolve } = Promise.withResolvers();
2199 const buffer = Buffer.from(compressedString, 'base64');
2200 zlib.brotliDecompress(buffer, (err, buffer) => {
2201 assert.ifError(err);
2202 assert.strictEqual(buffer.toString(), inputString);
2203 resolve();
2204 });
2205 
2206 await promise;
2207 }
2208 },
2209};
2210 
2211// Test taken from
2212// https://github.com/nodejs/node/blob/26eb062a9b9c0ae8cee9cb5c378e43bca363207c/test/parallel/test-zlib-maxOutputLength.js
2213export const maxOutputLength = {
2214 async test() {
2215 const encoded = Buffer.from('G38A+CXCIrFAIAM=', 'base64');
2216 
2217 // Async
2218 {
2219 const { promise, resolve } = Promise.withResolvers();
2220 zlib.brotliDecompress(encoded, { maxOutputLength: 64 }, (err) => {
2221 // TODO(soon): Make error the same as NodeJS
2222 assert.match(err.message, /Memory limit exceeded/);
2223 resolve();
2224 });
2225 await promise;
2226 }
2227 
2228 // Sync
2229 assert.throws(function () {
2230 zlib.brotliDecompressSync(encoded, { maxOutputLength: 64 });
2231 }, RangeError);
2232 
2233 // Async
2234 {
2235 const { promise, resolve } = Promise.withResolvers();
2236 zlib.brotliDecompress(encoded, { maxOutputLength: 256 }, function (err) {
2237 assert.strictEqual(err, null);
2238 resolve();
2239 });
2240 
2241 await promise;
2242 }
2243 
2244 // Sync
2245 zlib.brotliDecompressSync(encoded, { maxOutputLength: 256 });
2246 },
2247};
2248 
2249// Test for maxOutputLength: 0 - should throw immediately instead of infinite loop
2250export const maxOutputLengthZero = {
2251 async test() {
2252 const expectedError = {
2253 name: 'RangeError',
2254 message:
2255 /The value of "options\.maxOutputLength" is out of range\. It must be >= 1/,
2256 };
2257 
2258 // Sync zlib - deflateSync with maxOutputLength: 0 should throw
2259 assert.throws(
2260 () => zlib.deflateSync('data', { maxOutputLength: 0 }),
2261 expectedError
2262 );
2263 
2264 // Sync zlib - inflateSync with maxOutputLength: 0 should throw
2265 const compressed = zlib.deflateSync('data');
2266 assert.throws(
2267 () => zlib.inflateSync(compressed, { maxOutputLength: 0 }),
2268 expectedError
2269 );
2270 
2271 // Sync brotli - brotliCompressSync with maxOutputLength: 0 should throw
2272 assert.throws(
2273 () => zlib.brotliCompressSync('data', { maxOutputLength: 0 }),
2274 expectedError
2275 );
2276 
2277 // Sync brotli - brotliDecompressSync with maxOutputLength: 0 should throw
2278 const brotliCompressed = zlib.brotliCompressSync('data');
2279 assert.throws(
2280 () => zlib.brotliDecompressSync(brotliCompressed, { maxOutputLength: 0 }),
2281 expectedError
2282 );
2283 
2284 // Async zlib - deflate with maxOutputLength: 0 should error
2285 {
2286 const { promise, resolve } = Promise.withResolvers();
2287 zlib.deflate('data', { maxOutputLength: 0 }, (err) => {
2288 assert.match(err.message, expectedError.message);
2289 resolve();
2290 });
2291 await promise;
2292 }
2293 
2294 // Async brotli - brotliCompress with maxOutputLength: 0 should error
2295 {
2296 const { promise, resolve } = Promise.withResolvers();
2297 zlib.brotliCompress('data', { maxOutputLength: 0 }, (err) => {
2298 assert.match(err.message, expectedError.message);
2299 resolve();
2300 });
2301 await promise;
2302 }
2303 },
2304};
2305 
2306// Test taken from
2307// https://github.com/nodejs/node/blob/24302c9fe94e1dd755ac8a8cc1f6aa4444f75cb3/test/parallel/test-zlib-invalid-arg-value-brotli-compress.js
2308export const invalidArgValueBrotliCompress = {
2309 test() {
2310 const opts = {
2311 params: {
2312 [zlib.constants.BROTLI_PARAM_MODE]: 'lol',
2313 },
2314 };
2315 
2316 // TODO(soon): Node's test invokes BrotliCompress without new, but we barf if you try that.
2317 assert.throws(() => new zlib.BrotliCompress(opts), {
2318 code: 'ERR_INVALID_ARG_TYPE',
2319 });
2320 },
2321};
2322 
2323// Test taken from
2324// https://github.com/nodejs/node/blob/24302c9fe94e1dd755ac8a8cc1f6aa4444f75cb3/test/parallel/test-zlib-brotli-flush.js
2325export const brotliFlush = {
2326 async test() {
2327 const deflater = new zlib.BrotliCompress();
2328 
2329 const chunk = Buffer.from('/9j/4AAQSkZJRgABAQEASA==', 'base64');
2330 const expectedFull = Buffer.from('iweA/9j/4AAQSkZJRgABAQEASA==', 'base64');
2331 let actualFull;
2332 
2333 {
2334 const { promise, resolve } = Promise.withResolvers();
2335 deflater.write(chunk, function () {
2336 deflater.flush(function () {
2337 const bufs = [];
2338 let buf;
2339 while ((buf = deflater.read()) !== null) bufs.push(buf);
2340 actualFull = Buffer.concat(bufs);
2341 resolve();
2342 });
2343 });
2344 
2345 await promise;
2346 }
2347 assert.deepStrictEqual(actualFull, expectedFull);
2348 },
2349};
2350 
2351// Test taken from
2352// https://github.com/nodejs/node/blob/24302c9fe94e1dd755ac8a8cc1f6aa4444f75cb3/test/parallel/test-zlib-brotli.js
2353export const brotli = {
2354 async test() {
2355 {
2356 const sampleBuffer = Buffer.from(PSS_VECTORS_JSON);
2357 
2358 // Test setting the quality parameter at stream creation:
2359 const sizes = [];
2360 for (
2361 let quality = zlib.constants.BROTLI_MIN_QUALITY;
2362 quality <= zlib.constants.BROTLI_MAX_QUALITY;
2363 quality++
2364 ) {
2365 const encoded = zlib.brotliCompressSync(sampleBuffer, {
2366 params: {
2367 [zlib.constants.BROTLI_PARAM_QUALITY]: quality,
2368 },
2369 });
2370 sizes.push(encoded.length);
2371 }
2372 
2373 // Increasing quality should roughly correspond to decreasing compressed size:
2374 for (let i = 0; i < sizes.length - 1; i++) {
2375 assert(sizes[i + 1] <= sizes[i] * 1.05, sizes); // 5 % margin of error.
2376 }
2377 assert(sizes[0] > sizes[sizes.length - 1], sizes);
2378 }
2379 
2380 {
2381 // Test that setting out-of-bounds option values or keys fails.
2382 assert.throws(
2383 () => {
2384 zlib.createBrotliCompress({
2385 params: {
2386 10000: 0,
2387 },
2388 });
2389 },
2390 {
2391 code: 'ERR_BROTLI_INVALID_PARAM',
2392 name: 'RangeError',
2393 message: '10000 is not a valid Brotli parameter',
2394 }
2395 );
2396 
2397 // Test that accidentally using duplicate keys fails.
2398 assert.throws(
2399 () => {
2400 zlib.createBrotliCompress({
2401 params: {
2402 0: 0,
2403 '00': 0,
2404 },
2405 });
2406 },
2407 {
2408 code: 'ERR_BROTLI_INVALID_PARAM',
2409 name: 'RangeError',
2410 message: '00 is not a valid Brotli parameter',
2411 }
2412 );
2413 
2414 {
2415 assert.throws(
2416 () => {
2417 zlib.createBrotliCompress({
2418 params: {
2419 // This is a boolean flag
2420 [zlib.constants.BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING]:
2421 42,
2422 },
2423 });
2424 },
2425 {
2426 code: 'ERR_ZLIB_INITIALIZATION_FAILED',
2427 name: 'Error',
2428 message: 'Initialization failed',
2429 }
2430 );
2431 }
2432 
2433 {
2434 // Test options.flush range
2435 // TODO(soon): Use the same code and message as NodeJS
2436 assert.throws(
2437 () => {
2438 zlib.brotliCompressSync('', { flush: zlib.constants.Z_FINISH });
2439 },
2440 {
2441 //code: 'ERR_OUT_OF_RANGE',
2442 name: 'RangeError',
2443 message:
2444 'The value of "options.flush" is out of range. It must be >= 0 ' +
2445 'and <= 3. Received 4',
2446 }
2447 );
2448 
2449 assert.throws(
2450 () => {
2451 zlib.brotliCompressSync('', {
2452 finishFlush: zlib.constants.Z_FINISH,
2453 });
2454 },
2455 {
2456 //code: 'ERR_OUT_OF_RANGE',
2457 name: 'RangeError',
2458 message:
2459 'The value of "options.finishFlush" is out of range. It must be ' +
2460 '>= 0 and <= 3. Received 4',
2461 }
2462 );
2463 }
2464 }
2465 },
2466};
2467 
2468// Tests are taken from:
2469// https://github.com/nodejs/node/blob/2ef4b15604082abfd7aa26a4619a46802258ff3c/test/parallel/test-zlib-random-byte-pipes.js
2470export const zlibRandomBytePipes = {
2471 async test() {
2472 // Emit random bytes, and keep a shasum
2473 class RandomReadStream extends Stream {
2474 constructor(opt) {
2475 super();
2476 
2477 this.readable = true;
2478 this._paused = false;
2479 this._processing = false;
2480 this._hasher = crypto.createHash('sha1');
2481 opt ??= {};
2482 
2483 // base block size.
2484 opt.block ??= 256 * 1024;
2485 // Total number of bytes to emit
2486 opt.total ??= 256 * 1024 * 1024;
2487 this._remaining = opt.total;
2488 // How variable to make the block sizes
2489 opt.jitter ??= 1024;
2490 this._opt = opt;
2491 this._process = this._process.bind(this);
2492 queueMicrotask(this._process);
2493 }
2494 
2495 pause() {
2496 this._paused = true;
2497 this.emit('pause');
2498 }
2499 
2500 resume() {
2501 this._paused = false;
2502 this.emit('resume');
2503 this._process();
2504 }
2505 
2506 _process() {
2507 if (this._processing) return;
2508 if (this._paused) return;
2509 this._processing = true;
2510 
2511 if (!this._remaining) {
2512 this._hash = this._hasher.digest('hex').toLowerCase().trim();
2513 this._processing = false;
2514 
2515 this.emit('end');
2516 return;
2517 }
2518 
2519 // Figure out how many bytes to output
2520 // if finished, then just emit end.
2521 let block = this._opt.block;
2522 const jitter = this._opt.jitter;
2523 if (jitter) {
2524 block += Math.ceil(Math.random() * jitter - jitter / 2);
2525 }
2526 block = Math.min(block, this._remaining);
2527 const buf = Buffer.allocUnsafe(block);
2528 for (let i = 0; i < block; i++) {
2529 buf[i] = Math.random() * 256;
2530 }
2531 
2532 this._hasher.update(buf);
2533 this._remaining -= block;
2534 this._processing = false;
2535 this.emit('data', buf);
2536 queueMicrotask(this._process);
2537 }
2538 }
2539 
2540 // A filter that just verifies a shasum
2541 class HashStream extends Stream {
2542 constructor() {
2543 super();
2544 this.readable = this.writable = true;
2545 this._hasher = crypto.createHash('sha1');
2546 }
2547 
2548 write(c) {
2549 // Simulate the way that an fs.ReadStream returns false
2550 // on *every* write, only to resume a moment later.
2551 this._hasher.update(c);
2552 queueMicrotask(() => this.resume());
2553 return false;
2554 }
2555 
2556 resume() {
2557 this.emit('resume');
2558 queueMicrotask(() => this.emit('drain'));
2559 }
2560 
2561 end(c) {
2562 if (c) {
2563 this.write(c);
2564 }
2565 this._hash = this._hasher.digest('hex').toLowerCase().trim();
2566 this.emit('data', this._hash);
2567 this.emit('end');
2568 }
2569 }
2570 
2571 for (const [createCompress, createDecompress] of [
2572 [zlib.createGzip, zlib.createGunzip],
2573 [zlib.createBrotliCompress, zlib.createBrotliDecompress],
2574 ]) {
2575 const { promise, resolve, reject } = Promise.withResolvers();
2576 const inp = new RandomReadStream({ total: 1024, block: 256, jitter: 16 });
2577 const out = new HashStream();
2578 const gzip = createCompress();
2579 const gunz = createDecompress();
2580 
2581 inp.pipe(gzip).pipe(gunz).pipe(out);
2582 
2583 const onDataFn = mock.fn();
2584 onDataFn.mock.mockImplementation((c) => {
2585 assert.strictEqual(c, inp._hash, `Hash '${c}' equals '${inp._hash}'.`);
2586 });
2587 
2588 out.on('data', onDataFn).on('end', resolve).on('error', reject);
2589 
2590 await promise;
2591 
2592 assert.ok(onDataFn.mock.callCount() > 0, 'Should have called onData');
2593 }
2594 },
2595};
2596 
2597// Tests are taken from:
2598// https://github.com/nodejs/node/blob/2ef4b15604082abfd7aa26a4619a46802258ff3c/test/parallel/test-zlib-sync-no-event.js
2599export const zlibSyncNoEvent = {
2600 async test() {
2601 const { promise, resolve, reject } = Promise.withResolvers();
2602 const message = 'Come on, Fhqwhgads.';
2603 const buffer = Buffer.from(message);
2604 
2605 const zipper = new zlib.Gzip();
2606 zipper.on('close', reject);
2607 
2608 const zipped = zipper._processChunk(buffer, zlib.constants.Z_FINISH);
2609 
2610 const unzipper = new zlib.Gunzip();
2611 unzipper.on('close', reject);
2612 
2613 const unzipped = unzipper._processChunk(zipped, zlib.constants.Z_FINISH);
2614 assert.notStrictEqual(zipped.toString(), message);
2615 assert.strictEqual(unzipped.toString(), message);
2616 
2617 queueMicrotask(resolve);
2618 
2619 await promise;
2620 },
2621};
2622 
2623// Tests are taken from:
2624// https://github.com/nodejs/node/blob/2ef4b15604082abfd7aa26a4619a46802258ff3c/test/parallel/test-zlib-brotli-16GB.js
2625export const zlibBrotli16GB = {
2626 async test() {
2627 const { promise, resolve } = Promise.withResolvers();
2628 const content =
2629 'cfffff7ff82700e2b14020f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c32200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bffcfffff7ff82700e2b00040f7fe9ffffffff04f00c4610180eefd3fffffffe19f0088c30200ddfb7ffeffffc33f0110870500baf7fffcffff877f02200e0b0074effff9ffff0fff04401c1600e8defff3ffff1ffe0980382c00d0bdffe7ffff3ffc1300715800a07bff3f';
2630 const buf = Buffer.from(content, 'hex');
2631 const decoder = zlib.createBrotliDecompress();
2632 
2633 decoder.end(buf);
2634 
2635 queueMicrotask(() => {
2636 // There is only one chunk in the buffer
2637 assert.strictEqual(
2638 decoder._readableState.buffer.length,
2639 getDefaultHighWaterMark() / (16 * 1024)
2640 );
2641 resolve();
2642 });
2643 
2644 await promise;
2645 },
2646};
2647 
2648// Large test data is added at the end of the file in order to make the test code itself more readable
2649const PSS_VECTORS_JSON = `{
2650 "example01": {
2651 "publicKey": [
2652 "-----BEGIN PUBLIC KEY-----",
2653 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClbkoOcBAXWJpRh9x+qEHRVvLs",
2654 "DjatUqRN/rHmH3rZkdjFEFb/7bFitMDyg6EqiKOU3/Umq3KRy7MHzqv84LHf1c2V",
2655 "CAltWyuLbfXWce9jd8CSHLI8Jwpw4lmOb/idGfEFrMLT8Ms18pKA4Thrb2TE7yLh",
2656 "4fINDOjP+yJJvZohNwIDAQAB",
2657 "-----END PUBLIC KEY-----"
2658 ],
2659 "tests": [
2660 {
2661 "message": "cdc87da223d786df3b45e0bbbc721326d1ee2af806cc315475cc6f0d9c66e1b62371d45ce2392e1ac92844c310102f156a0d8d52c1f4c40ba3aa65095786cb769757a6563ba958fed0bcc984e8b517a3d5f515b23b8a41e74aa867693f90dfb061a6e86dfaaee64472c00e5f20945729cbebe77f06ce78e08f4098fba41f9d6193c0317e8b60d4b6084acb42d29e3808a3bc372d85e331170fcbf7cc72d0b71c296648b3a4d10f416295d0807aa625cab2744fd9ea8fd223c42537029828bd16be02546f130fd2e33b936d2676e08aed1b73318b750a0167d0",
2662 "salt": "dee959c7e06411361420ff80185ed57f3e6776af",
2663 "signature": "9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c"
2664 },
2665 {
2666 "message": "851384cdfe819c22ed6c4ccb30daeb5cf059bc8e1166b7e3530c4c233e2b5f8f71a1cca582d43ecc72b1bca16dfc7013226b9e",
2667 "salt": "ef2869fa40c346cb183dab3d7bffc98fd56df42d",
2668 "signature": "3ef7f46e831bf92b32274142a585ffcefbdca7b32ae90d10fb0f0c729984f04ef29a9df0780775ce43739b97838390db0a5505e63de927028d9d29b219ca2c4517832558a55d694a6d25b9dab66003c4cccd907802193be5170d26147d37b93590241be51c25055f47ef62752cfbe21418fafe98c22c4d4d47724fdb5669e843"
2669 },
2670 {
2671 "message": "a4b159941761c40c6a82f2b80d1b94f5aa2654fd17e12d588864679b54cd04ef8bd03012be8dc37f4b83af7963faff0dfa225477437c48017ff2be8191cf3955fc07356eab3f322f7f620e21d254e5db4324279fe067e0910e2e81ca2cab31c745e67a54058eb50d993cdb9ed0b4d029c06d21a94ca661c3ce27fae1d6cb20f4564d66ce4767583d0e5f060215b59017be85ea848939127bd8c9c4d47b51056c031cf336f17c9980f3b8f5b9b6878e8b797aa43b882684333e17893fe9caa6aa299f7ed1a18ee2c54864b7b2b99b72618fb02574d139ef50f019c9eef416971338e7d470",
2672 "salt": "710b9c4747d800d4de87f12afdce6df18107cc77",
2673 "signature": "666026fba71bd3e7cf13157cc2c51a8e4aa684af9778f91849f34335d141c00154c4197621f9624a675b5abc22ee7d5baaffaae1c9baca2cc373b3f33e78e6143c395a91aa7faca664eb733afd14d8827259d99a7550faca501ef2b04e33c23aa51f4b9e8282efdb728cc0ab09405a91607c6369961bc8270d2d4f39fce612b1"
2674 },
2675 {
2676 "message": "bc656747fa9eafb3f0",
2677 "salt": "056f00985de14d8ef5cea9e82f8c27bef720335e",
2678 "signature": "4609793b23e9d09362dc21bb47da0b4f3a7622649a47d464019b9aeafe53359c178c91cd58ba6bcb78be0346a7bc637f4b873d4bab38ee661f199634c547a1ad8442e03da015b136e543f7ab07c0c13e4225b8de8cce25d4f6eb8400f81f7e1833b7ee6e334d370964ca79fdb872b4d75223b5eeb08101591fb532d155a6de87"
2679 },
2680 {
2681 "message": "b45581547e5427770c768e8b82b75564e0ea4e9c32594d6bff706544de0a8776c7a80b4576550eee1b2acabc7e8b7d3ef7bb5b03e462c11047eadd00629ae575480ac1470fe046f13a2bf5af17921dc4b0aa8b02bee6334911651d7f8525d10f32b51d33be520d3ddf5a709955a3dfe78283b9e0ab54046d150c177f037fdccc5be4ea5f68b5e5a38c9d7edcccc4975f455a6909b4",
2682 "salt": "80e70ff86a08de3ec60972b39b4fbfdcea67ae8e",
2683 "signature": "1d2aad221ca4d31ddf13509239019398e3d14b32dc34dc5af4aeaea3c095af73479cf0a45e5629635a53a018377615b16cb9b13b3e09d671eb71e387b8545c5960da5a64776e768e82b2c93583bf104c3fdb23512b7b4e89f633dd0063a530db4524b01c3f384c09310e315a79dcd3d684022a7f31c865a664e316978b759fad"
2684 },
2685 {
2686 "message": "10aae9a0ab0b595d0841207b700d48d75faedde3b775cd6b4cc88ae06e4694ec74ba18f8520d4f5ea69cbbe7cc2beba43efdc10215ac4eb32dc302a1f53dc6c4352267e7936cfebf7c8d67035784a3909fa859c7b7b59b8e39c5c2349f1886b705a30267d402f7486ab4f58cad5d69adb17ab8cd0ce1caf5025af4ae24b1fb8794c6070cc09a51e2f9911311e3877d0044c71c57a993395008806b723ac38373d395481818528c1e7053739282053529510e935cd0fa77b8fa53cc2d474bd4fb3cc5c672d6ffdc90a00f9848712c4bcfe46c60573659b11e6457e861f0f604b6138d144f8ce4e2da73",
2687 "salt": "a8ab69dd801f0074c2a1fc60649836c616d99681",
2688 "signature": "2a34f6125e1f6b0bf971e84fbd41c632be8f2c2ace7de8b6926e31ff93e9af987fbc06e51e9be14f5198f91f3f953bd67da60a9df59764c3dc0fe08e1cbef0b75f868d10ad3fba749fef59fb6dac46a0d6e504369331586f58e4628f39aa278982543bc0eeb537dc61958019b394fb273f215858a0a01ac4d650b955c67f4c58"
2689 }
2690 ]
2691 },
2692 "example10": {
2693 "publicKey": [
2694 "-----BEGIN PUBLIC KEY-----",
2695 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApd2GesTLAvkLlFfUjBSn",
2696 "cO+ZHFbDnA7GX9Ea+ok3zqV7m+esc7RcABdhW4LWIuMYdTtgJ8D9FXvhL4CQ/uKn",
2697 "rc0O73WfiLpJl8ekLVjJqhLLma4AH+UhwTu1QxRFqNWuT15MfpSKwifTYEBx8g5X",
2698 "fpBfvrFd+vBtHeWuYlPWOmohILMaXaXavJVQYA4g8n03OeJieSX+o8xQnyHf8E5u",
2699 "6kVJxUDWgJ/5MH7t6R//WHM9g4WiN9bTcFoz45GQCZIHDfet8TV89+NwDONmfeg/",
2700 "F7jfF3jbOB3OCctK0FilEQAac4GY7ifPVaE7dUU5kGWC7IsXS9WNXR89dnxhNyGu",
2701 "BQIDAQAB",
2702 "-----END PUBLIC KEY-----"
2703 ],
2704 "tests": [
2705 {
2706 "message": "883177e5126b9be2d9a9680327d5370c6f26861f5820c43da67a3ad609",
2707 "salt": "04e215ee6ff934b9da70d7730c8734abfcecde89",
2708 "signature": "82c2b160093b8aa3c0f7522b19f87354066c77847abf2a9fce542d0e84e920c5afb49ffdfdace16560ee94a1369601148ebad7a0e151cf16331791a5727d05f21e74e7eb811440206935d744765a15e79f015cb66c532c87a6a05961c8bfad741a9a6657022894393e7223739796c02a77455d0f555b0ec01ddf259b6207fd0fd57614cef1a5573baaff4ec00069951659b85f24300a25160ca8522dc6e6727e57d019d7e63629b8fe5e89e25cc15beb3a647577559299280b9b28f79b0409000be25bbd96408ba3b43cc486184dd1c8e62553fa1af4040f60663de7f5e49c04388e257f1ce89c95dab48a315d9b66b1b7628233876ff2385230d070d07e1666"
2709 },
2710 {
2711 "message": "dd670a01465868adc93f26131957a50c52fb777cdbaa30892c9e12361164ec13979d43048118e4445db87bee58dd987b3425d02071d8dbae80708b039dbb64dbd1de5657d9fed0c118a54143742e0ff3c87f74e45857647af3f79eb0a14c9d75ea9a1a04b7cf478a897a708fd988f48e801edb0b7039df8c23bb3c56f4e821ac",
2712 "salt": "8b2bdd4b40faf545c778ddf9bc1a49cb57f9b71b",
2713 "signature": "14ae35d9dd06ba92f7f3b897978aed7cd4bf5ff0b585a40bd46ce1b42cd2703053bb9044d64e813d8f96db2dd7007d10118f6f8f8496097ad75e1ff692341b2892ad55a633a1c55e7f0a0ad59a0e203a5b8278aec54dd8622e2831d87174f8caff43ee6c46445345d84a59659bfb92ecd4c818668695f34706f66828a89959637f2bf3e3251c24bdba4d4b7649da0022218b119c84e79a6527ec5b8a5f861c159952e23ec05e1e717346faefe8b1686825bd2b262fb2531066c0de09acde2e4231690728b5d85e115a2f6b92b79c25abc9bd9399ff8bcf825a52ea1f56ea76dd26f43baafa18bfa92a504cbd35699e26d1dcc5a2887385f3c63232f06f3244c3"
2714 },
2715 {
2716 "message": "48b2b6a57a63c84cea859d65c668284b08d96bdcaabe252db0e4a96cb1bac6019341db6fbefb8d106b0e90eda6bcc6c6262f37e7ea9c7e5d226bd7df85ec5e71efff2f54c5db577ff729ff91b842491de2741d0c631607df586b905b23b91af13da12304bf83eca8a73e871ff9db",
2717 "salt": "4e96fc1b398f92b44671010c0dc3efd6e20c2d73",
2718 "signature": "6e3e4d7b6b15d2fb46013b8900aa5bbb3939cf2c095717987042026ee62c74c54cffd5d7d57efbbf950a0f5c574fa09d3fc1c9f513b05b4ff50dd8df7edfa20102854c35e592180119a70ce5b085182aa02d9ea2aa90d1df03f2daae885ba2f5d05afdac97476f06b93b5bc94a1a80aa9116c4d615f333b098892b25fface266f5db5a5a3bcc10a824ed55aad35b727834fb8c07da28fcf416a5d9b2224f1f8b442b36f91e456fdea2d7cfe3367268de0307a4c74e924159ed33393d5e0655531c77327b89821bdedf880161c78cd4196b5419f7acc3f13e5ebf161b6e7c6724716ca33b85c2e25640192ac2859651d50bde7eb976e51cec828b98b6563b86bb"
2719 },
2720 {
2721 "message": "0b8777c7f839baf0a64bbbdbc5ce79755c57a205b845c174e2d2e90546a089c4e6ec8adffa23a7ea97bae6b65d782b82db5d2b5a56d22a29a05e7c4433e2b82a621abba90add05ce393fc48a840542451a",
2722 "salt": "c7cd698d84b65128d8835e3a8b1eb0e01cb541ec",
2723 "signature": "34047ff96c4dc0dc90b2d4ff59a1a361a4754b255d2ee0af7d8bf87c9bc9e7ddeede33934c63ca1c0e3d262cb145ef932a1f2c0a997aa6a34f8eaee7477d82ccf09095a6b8acad38d4eec9fb7eab7ad02da1d11d8e54c1825e55bf58c2a23234b902be124f9e9038a8f68fa45dab72f66e0945bf1d8bacc9044c6f07098c9fcec58a3aab100c805178155f030a124c450e5acbda47d0e4f10b80a23f803e774d023b0015c20b9f9bbe7c91296338d5ecb471cafb032007b67a60be5f69504a9f01abb3cb467b260e2bce860be8d95bf92c0c8e1496ed1e528593a4abb6df462dde8a0968dffe4683116857a232f5ebf6c85be238745ad0f38f767a5fdbf486fb"
2724 },
2725 {
2726 "message": "f1036e008e71e964dadc9219ed30e17f06b4b68a955c16b312b1eddf028b74976bed6b3f6a63d4e77859243c9cccdc98016523abb02483b35591c33aad81213bb7c7bb1a470aabc10d44256c4d4559d916",
2727 "salt": "efa8bff96212b2f4a3f371a10d574152655f5dfb",
2728 "signature": "7e0935ea18f4d6c1d17ce82eb2b3836c55b384589ce19dfe743363ac9948d1f346b7bfddfe92efd78adb21faefc89ade42b10f374003fe122e67429a1cb8cbd1f8d9014564c44d120116f4990f1a6e38774c194bd1b8213286b077b0499d2e7b3f434ab12289c556684deed78131934bb3dd6537236f7c6f3dcb09d476be07721e37e1ceed9b2f7b406887bd53157305e1c8b4f84d733bc1e186fe06cc59b6edb8f4bd7ffefdf4f7ba9cfb9d570689b5a1a4109a746a690893db3799255a0cb9215d2d1cd490590e952e8c8786aa0011265252470c041dfbc3eec7c3cbf71c24869d115c0cb4a956f56d530b80ab589acfefc690751ddf36e8d383f83cedd2cc"
2729 },
2730 {
2731 "message": "25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7",
2732 "salt": "ad8b1523703646224b660b550885917ca2d1df28",
2733 "signature": "6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f"
2734 }
2735 ]
2736 }
2737}`;
2738 
2739export const compatFlagTest = {
2740 async test(_, env) {
2741 const waitForIt = async (test) => {
2742 const res = await env[test].fetch('http://example.org');
2743 return await res.text();
2744 };
2745 const results = await Promise.allSettled([
2746 waitForIt('compat'),
2747 waitForIt('compatv2'),
2748 waitForIt('compatNoV2'),
2749 ]);
2750 assert.deepStrictEqual(results, [
2751 { status: 'fulfilled', value: 'true' },
2752 { status: 'fulfilled', value: 'true' },
2753 { status: 'fulfilled', value: 'true' },
2754 ]);
2755 },
2756};
2757 
2758export const stateSizeTest = {
2759 test() {
2760 const Uint32Array_orig = Uint32Array;
2761 assert.throws(
2762 () => {
2763 const message = 'Come on, Fhqwhgads.';
2764 const buffer = Buffer.from(message);
2765 globalThis.Uint32Array = function (...args) {
2766 if (args.length == 1 && arguments[0] == 2) {
2767 return new Uint32Array_orig(new ArrayBuffer(32), 32);
2768 }
2769 return new Uint32Array_orig(...args);
2770 };
2771 
2772 const zipper = new zlib.Gzip();
2773 const zipped = zipper._processChunk(buffer, zlib.constants.FINISH);
2774 const unzipper = new zlib.Gunzip();
2775 unzipper._processChunk(zipped, zlib.constants.FINISH);
2776 },
2777 {
2778 message: /Invalid write result buffer/,
2779 }
2780 );
2781 globalThis.Uint32Array = Uint32Array_orig;
2782 },
2783};
2784 
2785export const zlibStreamTest = {
2786 async test() {
2787 const imgBase64 =
2788 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII';
2789 
2790 const buf = Buffer.from(imgBase64, 'base64');
2791 const imageStream = Readable.from(Buffer.from(imgBase64, 'base64'));
2792 const g = zlib.createGzip();
2793 
2794 const { promise, resolve } = Promise.withResolvers();
2795 const chunks = [];
2796 const w = new Writable({
2797 construct(callback) {
2798 // Double queueMicrotask is intentional to reproduce the bug.
2799 // Do not remove any of them.
2800 queueMicrotask(() => {
2801 queueMicrotask(() => {
2802 callback(null);
2803 });
2804 });
2805 },
2806 write(chunk, encoding, callback) {
2807 chunks.push(chunk);
2808 callback();
2809 },
2810 });
2811 w.on('close', resolve);
2812 const pp = imageStream.pipe(g);
2813 pp.pipe(w);
2814 
2815 await promise;
2816 
2817 assert.strictEqual(
2818 zlib.gunzipSync(Buffer.concat(chunks)).toString('hex'),
2819 buf.toString('hex')
2820 );
2821 },
2822};
2823 
2824// Regression test: after writeSync() returns, z_stream must not retain stale
2825// buffer pointers. When handle.params() is called directly (bypassing the
2826// TypeScript wrapper's flush-before-params protection), deflateParams() may
2827// internally call deflate(Z_BLOCK) to flush pending data. Before the fix,
2828// z_stream.next_out still pointed into the kj::Array that backed the output
2829// buffer — memory whose BackingStore ref had already been released. If the
2830// JS ArrayBuffer was then garbage-collected, that write went to freed memory.
2831// The fix clears z_stream buffer pointers after every write, so
2832// deflateParams() sees avail_out=0 and returns Z_BUF_ERROR (non-fatal)
2833// instead of writing through a dangling pointer.
2834export const zlibParamsAfterWriteNoStalePointers = {
2835 test() {
2836 // Configuration that leaves data pending in zlib's internal buffers:
2837 // level 0 (stored blocks) + minimum memory/window + Z_NO_FLUSH.
2838 const deflate = zlib.createDeflateRaw({
2839 level: 0,
2840 memLevel: 1,
2841 windowBits: 9,
2842 });
2843 
2844 const handle = deflate._handle;
2845 assert.ok(handle, 'native handle should be accessible');
2846 
2847 const input = Buffer.from('A'.repeat(64));
2848 const output1 = Buffer.alloc(1024);
2849 
2850 // Step 1: writeSync with Z_NO_FLUSH — data is buffered internally.
2851 handle.writeSync(0, input, 0, input.length, output1, 0, output1.length);
2852 
2853 // Capture how many bytes were produced so far.
2854 const state = deflate._writeState;
2855 const bytesOut1 = output1.length - state[0];
2856 
2857 // Step 2: params() directly on native handle — no preceding flush.
2858 // Before the fix this could write to a stale next_out pointer.
2859 // After the fix this safely returns Z_BUF_ERROR (handled as non-fatal).
2860 handle.params(
2861 zlib.constants.Z_DEFAULT_COMPRESSION,
2862 zlib.constants.Z_DEFAULT_STRATEGY
2863 );
2864 
2865 // Step 3: finish the stream — must still produce a valid deflate stream.
2866 const output2 = Buffer.alloc(1024);
2867 handle.writeSync(
2868 zlib.constants.Z_FINISH,
2869 Buffer.alloc(0),
2870 0,
2871 0,
2872 output2,
2873 0,
2874 output2.length
2875 );
2876 const bytesOut2 = output2.length - state[0];
2877 
2878 // Step 4: concatenate both output chunks and decompress.
2879 const compressed = Buffer.concat([
2880 output1.slice(0, bytesOut1),
2881 output2.slice(0, bytesOut2),
2882 ]);
2883 const decompressed = zlib.inflateRawSync(compressed, { windowBits: 9 });
2884 assert.strictEqual(
2885 decompressed.toString(),
2886 input.toString(),
2887 'round-trip through write/params/finish must preserve data'
2888 );
2889 },
2890};
2891 
2892// Regression test for https://github.com/cloudflare/workerd/issues/6286
2893// inflateRawSync throws "Memory limit exceeded" when maxOutputLength is set
2894// to exactly the decompressed size. This is an off-by-one error in the
2895// GrowableBuffer: after zlib fills the buffer completely (avail_out == 0),
2896// the processing loop tries to add another chunk which exceeds maxCapacity.
2897export const maxOutputLengthExactSize = {
2898 test() {
2899 // Create a known payload and compress it with deflateRaw
2900 const original = Buffer.from('a]b]c]d]e]f]g]h]i]j]k]l]m]n]o]p]'.repeat(32));
2901 const compressed = zlib.deflateRawSync(original);
2902 const exactSize = original.length;
2903 
2904 // This should succeed — maxOutputLength is exactly the output size.
2905 // Before the fix, this throws RangeError: "Memory limit exceeded"
2906 const decompressed = zlib.inflateRawSync(compressed, {
2907 maxOutputLength: exactSize,
2908 });
2909 assert.deepStrictEqual(decompressed, original);
2910 
2911 // Sanity check: maxOutputLength + 1 also works
2912 const decompressed2 = zlib.inflateRawSync(compressed, {
2913 maxOutputLength: exactSize + 1,
2914 });
2915 assert.deepStrictEqual(decompressed2, original);
2916 
2917 // Same bug affects inflateSync
2918 const compressedZlib = zlib.deflateSync(original);
2919 const decompressed3 = zlib.inflateSync(compressedZlib, {
2920 maxOutputLength: exactSize,
2921 });
2922 assert.deepStrictEqual(decompressed3, original);
2923 
2924 // And gunzipSync
2925 const compressedGzip = zlib.gzipSync(original);
2926 const decompressed4 = zlib.gunzipSync(compressedGzip, {
2927 maxOutputLength: exactSize,
2928 });
2929 assert.deepStrictEqual(decompressed4, original);
2930 
2931 // And brotliDecompressSync
2932 const compressedBrotli = zlib.brotliCompressSync(original);
2933 const decompressed5 = zlib.brotliDecompressSync(compressedBrotli, {
2934 maxOutputLength: exactSize,
2935 });
2936 assert.deepStrictEqual(decompressed5, original);
2937 
2938 // Verify that a maxOutputLength that's genuinely too small still throws
2939 assert.throws(
2940 () => zlib.inflateRawSync(compressed, { maxOutputLength: exactSize - 1 }),
2941 RangeError
2942 );
2943 },
2944};
2945 
2946// Regression test for the exception-safety gap in the clearBuffers() fix.
2947//
2948// When the writeState buffer passed to initialize() is too small (fewer
2949// than 2 uint32 elements), updateWriteResult() throws after deflate()
2950// has already run. The original clearBuffers() fix placed explicit calls
2951// *after* updateWriteResult(), so the exception unwinds past them —
2952// leaving z_stream.next_out pointing into the output buffer's BackingStore.
2953// If that buffer is later garbage-collected, a subsequent call to
2954// params() -> deflateParams() -> flush_pending() writes to freed memory.
2955//
2956// The fix uses KJ_DEFER so clearBuffers() runs on every scope exit,
2957// including exception unwinding.
2958//
2959// NOTE: The actual UAF only manifests when GC frees the backing stores
2960// (detectable via ASAN + forced gc()). This test exercises the vulnerable
2961// code path to guard against regressions and ensure no crash occurs; the
2962// memory-safety guarantee is provided by the KJ_DEFER fix itself.
2963export const zlibParamsAfterFailedWriteNoStalePointers = {
2964 test() {
2965 const streams = [];
2966 for (let j = 0; j < 10; j++) {
2967 // Access the native handle directly and re-initialize with a writeState
2968 // buffer that is intentionally too small (1 uint32 instead of 2).
2969 // This causes updateWriteResult() to throw after a successful deflate.
2970 const handle = new zlib.DeflateRaw({ level: 0 })._handle;
2971 handle.initialize(
2972 15,
2973 0,
2974 8,
2975 0,
2976 Buffer.from(new Uint32Array(1).buffer),
2977 () => {},
2978 undefined
2979 );
2980 
2981 const payload = Buffer.alloc(64, 0x41);
2982 let outputBuffer = Buffer.alloc(4096);
2983 
2984 // writeSync succeeds in deflate() but throws in updateWriteResult()
2985 // due to the undersized writeState. Before the KJ_DEFER fix, this
2986 // left z_stream.next_out pointing into outputBuffer.
2987 try {
2988 handle.writeSync(
2989 0,
2990 payload,
2991 0,
2992 payload.length,
2993 outputBuffer,
2994 0,
2995 outputBuffer.length
2996 );
2997 } catch (_e) {
2998 // Expected: "Invalid write result buffer"
2999 }
3000 streams.push({ handle, outputBuffer });
3001 }
3002 
3003 // Drop JS references to output buffers.
3004 for (const s of streams) s.outputBuffer = null;
3005 
3006 // params() calls deflateParams() which may internally flush. Before the
3007 // fix, this could write through a dangling next_out pointer. After the
3008 // fix, next_out points to a safe dummy byte with avail_out=0, so
3009 // deflateParams() returns Z_BUF_ERROR (non-fatal).
3010 for (const s of streams) {
3011 try {
3012 s.handle.params(
3013 zlib.constants.Z_DEFAULT_COMPRESSION,
3014 zlib.constants.Z_DEFAULT_STRATEGY
3015 );
3016 } catch (_e) {
3017 // May throw due to stream state; that's fine — the point is no UAF.
3018 }
3019 }
3020 },
3021};