pure-md5 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -24
- package/dist/adapters/ie11.cjs +1 -2
- package/dist/adapters/ie11.js +1 -2
- package/dist/adapters/node.cjs +1 -2
- package/dist/adapters/node.js +1 -2
- package/dist/adapters/webcrypto.cjs +1 -2
- package/dist/adapters/webcrypto.js +1 -2
- package/dist/index.cjs +1 -2
- package/dist/index.d.ts +149 -5
- package/dist/index.js +3 -2
- package/dist/md5.cjs +1 -0
- package/dist/md5.d.ts +20 -0
- package/dist/md5.js +1 -0
- package/dist/stream/md5-stream.cjs +1 -2
- package/dist/stream/md5-stream.js +1 -2
- package/dist/stream/whatwg-stream.cjs +1 -2
- package/dist/stream/whatwg-stream.js +1 -2
- package/dist/utils/detect.cjs +1 -2
- package/dist/utils/detect.js +3 -2
- package/package.json +10 -15
- package/pure-md5-0.2.1.tgz +0 -0
- package/test-tree-shake.mjs +12 -0
- package/.aliases +0 -19
- package/.bash_profile +0 -12
- package/.bash_prompt +0 -56
- package/.changeset/README.md +0 -32
- package/.changeset/config.json +0 -16
- package/.continue/mcpServers/new-mcp-server.yaml +0 -10
- package/.continue/rules +0 -29
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -35
- package/.github/ISSUE_TEMPLATE/documentation.md +0 -20
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -35
- package/.github/workflows/npm-publish.yml +0 -33
- package/.github/workflows/release.yml +0 -42
- package/CHANGELOG.md +0 -9
- package/CONTRIBUTING.md +0 -203
- package/MIGRATION_GUIDE_STREAMS.md +0 -374
- package/STREAM_API.md +0 -582
- package/STREAM_BENCHMARKS.md +0 -232
- package/STREAM_EXAMPLES.md +0 -669
- package/STREAM_OPTIMIZATION_REPORT.md +0 -136
- package/STREAM_TROUBLESHOOTING.md +0 -537
- package/WEB_CRYPTO_TESTS_SUMMARY.md +0 -140
- package/WHATWG_STREAMS.md +0 -191
- package/__tests__/adapters/node-crypto.test.ts +0 -167
- package/__tests__/adapters/web-crypto-node.test.ts +0 -73
- package/__tests__/adapters/web-crypto.test.ts +0 -195
- package/__tests__/add32.test.ts +0 -33
- package/__tests__/fallback.test.ts +0 -345
- package/__tests__/hex.test.ts +0 -38
- package/__tests__/hex_chr.test.ts +0 -20
- package/__tests__/index.test.ts +0 -87
- package/__tests__/integration/fixtures/test-file.txt +0 -1
- package/__tests__/integration/md5-stream-file.test.ts +0 -293
- package/__tests__/integration/node-crypto-file.test.ts +0 -86
- package/__tests__/integration/web-crypto.test.ts +0 -38
- package/__tests__/md51.test.ts +0 -73
- package/__tests__/md5block.test.ts +0 -61
- package/__tests__/md5cycle.test.ts +0 -48
- package/__tests__/round-functions.test.ts +0 -87
- package/__tests__/stream/fs-utils.test.ts +0 -209
- package/__tests__/stream/md5-stream-edge-cases.test.ts +0 -461
- package/__tests__/stream/md5-stream.test.ts +0 -418
- package/__tests__/stream/whatwg-stream.test.ts +0 -355
- package/__tests__/stream/whatwg-stream.test.ts.bak2 +0 -335
- package/benchmarks/md5-stream.bench.ts +0 -212
- package/benchmarks/whatwg-stream.bench.ts +0 -180
- package/dist/adapters/ie11.cjs.map +0 -1
- package/dist/adapters/ie11.js.map +0 -1
- package/dist/adapters/node.cjs.map +0 -1
- package/dist/adapters/node.js.map +0 -1
- package/dist/adapters/webcrypto.cjs.map +0 -1
- package/dist/adapters/webcrypto.js.map +0 -1
- package/dist/chunk-2YXXFGBV.js +0 -2
- package/dist/chunk-2YXXFGBV.js.map +0 -1
- package/dist/chunk-4KSCMS4Q.js +0 -2
- package/dist/chunk-4KSCMS4Q.js.map +0 -1
- package/dist/chunk-6P2QV5SR.js +0 -4
- package/dist/chunk-6P2QV5SR.js.map +0 -1
- package/dist/chunk-G5WHEAIQ.js +0 -2
- package/dist/chunk-G5WHEAIQ.js.map +0 -1
- package/dist/chunk-H2K353LR.js +0 -2
- package/dist/chunk-H2K353LR.js.map +0 -1
- package/dist/chunk-JKVD5LHZ.js +0 -2
- package/dist/chunk-JKVD5LHZ.js.map +0 -1
- package/dist/chunk-NWQ4N5RX.js +0 -2
- package/dist/chunk-NWQ4N5RX.js.map +0 -1
- package/dist/chunk-PHZ7FTYF.js +0 -2
- package/dist/chunk-PHZ7FTYF.js.map +0 -1
- package/dist/chunk-PNZTVQA7.js +0 -2
- package/dist/chunk-PNZTVQA7.js.map +0 -1
- package/dist/chunk-R4JB5MBR.js +0 -2
- package/dist/chunk-R4JB5MBR.js.map +0 -1
- package/dist/chunk-VFOAY6XI.js +0 -2
- package/dist/chunk-VFOAY6XI.js.map +0 -1
- package/dist/chunk-XB5BQIEX.js +0 -2
- package/dist/chunk-XB5BQIEX.js.map +0 -1
- package/dist/core/index.cjs +0 -2
- package/dist/core/index.cjs.map +0 -1
- package/dist/core/index.d.cts +0 -19
- package/dist/core/index.d.ts +0 -19
- package/dist/core/index.js +0 -2
- package/dist/core/index.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -84
- package/dist/index.js.map +0 -1
- package/dist/stream/adapter.cjs +0 -2
- package/dist/stream/adapter.cjs.map +0 -1
- package/dist/stream/adapter.d.cts +0 -63
- package/dist/stream/adapter.d.ts +0 -63
- package/dist/stream/adapter.js +0 -2
- package/dist/stream/adapter.js.map +0 -1
- package/dist/stream/fs-utils.cjs +0 -2
- package/dist/stream/fs-utils.cjs.map +0 -1
- package/dist/stream/fs-utils.d.cts +0 -137
- package/dist/stream/fs-utils.d.ts +0 -137
- package/dist/stream/fs-utils.js +0 -2
- package/dist/stream/fs-utils.js.map +0 -1
- package/dist/stream/index.cjs +0 -2
- package/dist/stream/index.cjs.map +0 -1
- package/dist/stream/index.d.cts +0 -4
- package/dist/stream/index.d.ts +0 -4
- package/dist/stream/index.js +0 -2
- package/dist/stream/index.js.map +0 -1
- package/dist/stream/light/index.cjs +0 -2
- package/dist/stream/light/index.cjs.map +0 -1
- package/dist/stream/light/index.d.cts +0 -4
- package/dist/stream/light/index.d.ts +0 -4
- package/dist/stream/light/index.js +0 -2
- package/dist/stream/light/index.js.map +0 -1
- package/dist/stream/md5-stream.cjs.map +0 -1
- package/dist/stream/md5-stream.js.map +0 -1
- package/dist/stream/whatwg-stream.cjs.map +0 -1
- package/dist/stream/whatwg-stream.js.map +0 -1
- package/dist/types-edGoGJ5V.d.cts +0 -42
- package/dist/types-edGoGJ5V.d.ts +0 -42
- package/dist/utils/detect.cjs.map +0 -1
- package/dist/utils/detect.js.map +0 -1
- package/planning/03-optimization-size-tree-shaking/01-es-modules-tree-shaking.md +0 -152
- package/planning/03-optimization-size-tree-shaking/02-consolidate-modules.md +0 -65
- package/planning/03-optimization-size-tree-shaking/03-remove-duplicate-add32.md +0 -93
- package/planning/03-optimization-size-tree-shaking/04-remove-runtime-check.md +0 -102
- package/planning/03-optimization-size-tree-shaking/05-optimize-loops-performance.md +0 -107
- package/planning/03-optimization-size-tree-shaking/06-tsup-formats-configuration.md +0 -227
- package/planning/03-optimization-size-tree-shaking/07-multiple-build-formats.md +0 -228
- package/planning/03-optimization-size-tree-shaking/08-benchmarks-metrics.md +0 -34
- package/planning/03-optimization-size-tree-shaking/MIGRATION_GUIDE.md +0 -260
- package/planning/03-optimization-size-tree-shaking/README.md +0 -173
- package/planning/03-optimization-size-tree-shaking/SUMMARY.md +0 -168
- package/planning/04-adapter-backend/03-backend-web-crypto.md +0 -149
- package/planning/04-adapter-backend/04-backend-node-crypto.md +0 -181
- package/planning/04-adapter-backend/05-backend-pure-js.md +0 -174
- package/planning/04-adapter-backend/06-backend-ie11.md +0 -158
- package/planning/04-adapter-backend/07-detection-environment.md +0 -232
- package/planning/04-adapter-backend/08-detection-backend.md +0 -210
- package/planning/04-adapter-backend/09-adapter-unified.md +0 -255
- package/planning/04-adapter-backend/10-fallback-mechanism.md +0 -333
- package/planning/04-adapter-backend/11-tests-backend-web-crypto.md +0 -191
- package/planning/04-adapter-backend/12-tests-backend-node-crypto.md +0 -222
- package/planning/04-adapter-backend/README.md +0 -45
- package/planning/05-documentation-publishing/01-README-optimization.md +0 -105
- package/planning/05-documentation-publishing/02-VitePress-site-evaluation.md +0 -136
- package/planning/05-documentation-publishing/03-Changeset-setup.md +0 -192
- package/planning/05-documentation-publishing/04-GitHub-templates.md +0 -252
- package/planning/05-documentation-publishing/README.md +0 -22
- package/planning/05-documentation-publishing/STATUS.md +0 -222
- package/planning/prd.md +0 -405
- package/planning/streams/01-create-md5stream-class.md +0 -69
- package/planning/streams/02-create-factory-api.md +0 -65
- package/planning/streams/03-fs-integration.md +0 -37
- package/planning/streams/04-whatwg-streams-support.md +0 -37
- package/planning/streams/05-audit-optimization.md +0 -121
- package/planning/streams/06-comprehensive-tests-docs.md +0 -137
- package/planning/streams/07-architecture-integration.md +0 -38
- package/planning/streams/README.md +0 -98
- package/tsup.config.ts +0 -24
|
@@ -1,355 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WHATWG Streams tests for browser environments
|
|
3
|
-
* These tests verify the WHATWG Streams implementation works correctly
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { MD5ReadableStream, hashBlob } from '../../src/stream/whatwg-stream.js';
|
|
7
|
-
import { md5Core } from '../../src/core/index.js';
|
|
8
|
-
|
|
9
|
-
// Skip tests if WHATWG Streams are not available
|
|
10
|
-
const canRunWhatwgTests = typeof ReadableStream !== 'undefined' && typeof Blob !== 'undefined';
|
|
11
|
-
|
|
12
|
-
if (!canRunWhatwgTests) {
|
|
13
|
-
console.log('WHATWG Streams not available, skipping tests');
|
|
14
|
-
// Create empty tests to satisfy Jest requirement
|
|
15
|
-
describe('MD5ReadableStream', () => {
|
|
16
|
-
it('should skip when WHATWG Streams not available', () => {
|
|
17
|
-
console.log('Skipping: WHATWG Streams not available');
|
|
18
|
-
});
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
describe('hashBlob', () => {
|
|
22
|
-
it('should skip when WHATWG Streams not available', () => {
|
|
23
|
-
console.log('Skipping: WHATWG Streams not available');
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
describe('integration', () => {
|
|
28
|
-
it('should skip when WHATWG Streams not available', () => {
|
|
29
|
-
console.log('Skipping: WHATWG Streams not available');
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
} else {
|
|
33
|
-
|
|
34
|
-
// Mock FileReader for Node.js environment
|
|
35
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
36
|
-
(global as any).FileReader = class {
|
|
37
|
-
static readonly EMPTY = 0;
|
|
38
|
-
static readonly LOADING = 1;
|
|
39
|
-
static readonly DONE = 2;
|
|
40
|
-
|
|
41
|
-
_result: ArrayBuffer | string | null = null;
|
|
42
|
-
onload: ((event: any) => void) | null = null;
|
|
43
|
-
onerror: ((event: any) => void) | null = null;
|
|
44
|
-
|
|
45
|
-
readAsArrayBuffer(blob: Blob) {
|
|
46
|
-
blob.arrayBuffer().then((buffer) => {
|
|
47
|
-
this._result = buffer;
|
|
48
|
-
this.onload?.({
|
|
49
|
-
target: {
|
|
50
|
-
result: buffer
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
}).catch((error) => {
|
|
54
|
-
this.onerror?.({ error });
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
describe('MD5ReadableStream', () => {
|
|
60
|
-
test('should compute MD5 hash for empty stream', async () => {
|
|
61
|
-
const source = new ReadableStream({
|
|
62
|
-
start(controller) {
|
|
63
|
-
controller.close();
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
const result = await MD5ReadableStream.hash(source);
|
|
68
|
-
|
|
69
|
-
expect(result.digest).toBe(md5Core(''));
|
|
70
|
-
expect(result.bytesProcessed).toBe(0);
|
|
71
|
-
}, 10000);
|
|
72
|
-
|
|
73
|
-
test('should compute MD5 hash for simple string', async () => {
|
|
74
|
-
const input = 'hello';
|
|
75
|
-
const source = new ReadableStream({
|
|
76
|
-
start(controller) {
|
|
77
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
78
|
-
controller.close();
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
const result = await MD5ReadableStream.hash(source);
|
|
83
|
-
|
|
84
|
-
expect(result.digest).toBe(md5Core(input));
|
|
85
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
86
|
-
}, 10000);
|
|
87
|
-
|
|
88
|
-
test('should compute MD5 hash for longer string', async () => {
|
|
89
|
-
const input = 'a'.repeat(1000);
|
|
90
|
-
const source = new ReadableStream({
|
|
91
|
-
start(controller) {
|
|
92
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
93
|
-
controller.close();
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
const result = await MD5ReadableStream.hash(source);
|
|
98
|
-
|
|
99
|
-
expect(result.digest).toBe(md5Core(input));
|
|
100
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
101
|
-
}, 10000);
|
|
102
|
-
|
|
103
|
-
test('should process chunked data correctly', async () => {
|
|
104
|
-
const input = 'hello world';
|
|
105
|
-
const source = new ReadableStream({
|
|
106
|
-
start(controller) {
|
|
107
|
-
controller.enqueue(new TextEncoder().encode('hello '));
|
|
108
|
-
controller.enqueue(new TextEncoder().encode('world'));
|
|
109
|
-
controller.close();
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
const result = await MD5ReadableStream.hash(source);
|
|
114
|
-
|
|
115
|
-
expect(result.digest).toBe(md5Core(input));
|
|
116
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
117
|
-
}, 10000);
|
|
118
|
-
|
|
119
|
-
test('should handle multiple chunks of varying sizes', async () => {
|
|
120
|
-
const input = 'This is a test string with multiple chunks';
|
|
121
|
-
const chunks = ['This ', 'is a', ' test', ' string', ' with', ' multi', 'ple c', 'hunks'];
|
|
122
|
-
|
|
123
|
-
const source = new ReadableStream({
|
|
124
|
-
start(controller) {
|
|
125
|
-
chunks.forEach(chunk => controller.enqueue(new TextEncoder().encode(chunk)));
|
|
126
|
-
controller.close();
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
const result = await MD5ReadableStream.hash(source);
|
|
131
|
-
|
|
132
|
-
expect(result.digest).toBe(md5Core(input));
|
|
133
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
134
|
-
}, 10000);
|
|
135
|
-
|
|
136
|
-
test('should handle data that exactly fills 64-byte blocks', async () => {
|
|
137
|
-
const input = 'a'.repeat(64);
|
|
138
|
-
const source = new ReadableStream({
|
|
139
|
-
start(controller) {
|
|
140
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
141
|
-
controller.close();
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
const result = await MD5ReadableStream.hash(source);
|
|
146
|
-
|
|
147
|
-
expect(result.digest).toBe(md5Core(input));
|
|
148
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
149
|
-
}, 10000);
|
|
150
|
-
|
|
151
|
-
test('should handle data that is multiple of 64 bytes', async () => {
|
|
152
|
-
const input = 'a'.repeat(128);
|
|
153
|
-
const source = new ReadableStream({
|
|
154
|
-
start(controller) {
|
|
155
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
156
|
-
controller.close();
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
const result = await MD5ReadableStream.hash(source);
|
|
161
|
-
|
|
162
|
-
expect(result.digest).toBe(md5Core(input));
|
|
163
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
164
|
-
}, 10000);
|
|
165
|
-
|
|
166
|
-
test('should handle special characters', async () => {
|
|
167
|
-
const input = '!@#$%^&*()_+-=[]{}|;:,.<>?';
|
|
168
|
-
const source = new ReadableStream({
|
|
169
|
-
start(controller) {
|
|
170
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
171
|
-
controller.close();
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
const result = await MD5ReadableStream.hash(source);
|
|
176
|
-
|
|
177
|
-
expect(result.digest).toBe(md5Core(input));
|
|
178
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
179
|
-
}, 10000);
|
|
180
|
-
|
|
181
|
-
test('should emit bytesProcessed correctly', async () => {
|
|
182
|
-
const totalBytes = 256;
|
|
183
|
-
const chunkSize = 64;
|
|
184
|
-
|
|
185
|
-
const source = new ReadableStream({
|
|
186
|
-
start(controller) {
|
|
187
|
-
const chunk = new TextEncoder().encode('a'.repeat(chunkSize));
|
|
188
|
-
for (let i = 0; i < 4; i++) {
|
|
189
|
-
controller.enqueue(chunk);
|
|
190
|
-
}
|
|
191
|
-
controller.close();
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
const result = await MD5ReadableStream.hash(source);
|
|
196
|
-
|
|
197
|
-
expect(result.bytesProcessed).toBe(totalBytes);
|
|
198
|
-
expect(result.digest.length).toBe(32);
|
|
199
|
-
}, 10000);
|
|
200
|
-
|
|
201
|
-
test('should support custom add32 function', async () => {
|
|
202
|
-
const input = 'custom add32 test';
|
|
203
|
-
const source = new ReadableStream({
|
|
204
|
-
start(controller) {
|
|
205
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
206
|
-
controller.close();
|
|
207
|
-
}
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
const customAdd32 = (x: number, y: number) => (x + y) & 0xffffffff;
|
|
211
|
-
const result = await MD5ReadableStream.hash(source, { add32: customAdd32 });
|
|
212
|
-
|
|
213
|
-
expect(result.digest).toBe(md5Core(input));
|
|
214
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
215
|
-
}, 10000);
|
|
216
|
-
|
|
217
|
-
test('should handle sequential processing', async () => {
|
|
218
|
-
const parts = ['Hello, ', 'World!', ' This is ', 'MD5 streaming.'];
|
|
219
|
-
const full = parts.join('');
|
|
220
|
-
|
|
221
|
-
const source = new ReadableStream({
|
|
222
|
-
start(controller) {
|
|
223
|
-
parts.forEach(part => controller.enqueue(new TextEncoder().encode(part)));
|
|
224
|
-
controller.close();
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
const result = await MD5ReadableStream.hash(source);
|
|
229
|
-
|
|
230
|
-
expect(result.digest).toBe(md5Core(full));
|
|
231
|
-
expect(result.bytesProcessed).toBe(full.length);
|
|
232
|
-
}, 10000);
|
|
233
|
-
|
|
234
|
-
test('should handle single byte chunks', async () => {
|
|
235
|
-
const input = 'a';
|
|
236
|
-
const source = new ReadableStream({
|
|
237
|
-
start(controller) {
|
|
238
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
239
|
-
controller.close();
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
const result = await MD5ReadableStream.hash(source);
|
|
244
|
-
|
|
245
|
-
expect(result.digest).toBe(md5Core(input));
|
|
246
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
247
|
-
}, 10000);
|
|
248
|
-
|
|
249
|
-
test('should emit valid hex digest', async () => {
|
|
250
|
-
const source = new ReadableStream({
|
|
251
|
-
start(controller) {
|
|
252
|
-
controller.enqueue(new TextEncoder().encode('test'));
|
|
253
|
-
controller.close();
|
|
254
|
-
}
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
const result = await MD5ReadableStream.hash(source);
|
|
258
|
-
|
|
259
|
-
// MD5 digest should be 32 hex characters
|
|
260
|
-
expect(result.digest).toMatch(/^[0-9a-f]{32}$/);
|
|
261
|
-
expect(result.digest.length).toBe(32);
|
|
262
|
-
}, 10000);
|
|
263
|
-
|
|
264
|
-
test('should get current state during processing', async () => {
|
|
265
|
-
const source = new ReadableStream({
|
|
266
|
-
start(controller) {
|
|
267
|
-
controller.enqueue(new TextEncoder().encode('test'));
|
|
268
|
-
controller.close();
|
|
269
|
-
}
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
const stream = new MD5ReadableStream(source);
|
|
273
|
-
|
|
274
|
-
// Check initial state before reading
|
|
275
|
-
const initialState = stream.getCurrentState();
|
|
276
|
-
expect(initialState.state).toHaveLength(4);
|
|
277
|
-
expect(initialState.bytesProcessed).toBe(0);
|
|
278
|
-
|
|
279
|
-
// Read some data
|
|
280
|
-
const reader = stream.getReader();
|
|
281
|
-
await reader.read();
|
|
282
|
-
|
|
283
|
-
// Check state after reading
|
|
284
|
-
const afterDataState = stream.getCurrentState();
|
|
285
|
-
expect(afterDataState.bytesProcessed).toBe(4);
|
|
286
|
-
|
|
287
|
-
// Check bytes processed getter
|
|
288
|
-
expect(stream.getBytesProcessed()).toBe(4);
|
|
289
|
-
}, 10000);
|
|
290
|
-
|
|
291
|
-
test('should handle empty chunks', async () => {
|
|
292
|
-
const input = 'test';
|
|
293
|
-
const source = new ReadableStream({
|
|
294
|
-
start(controller) {
|
|
295
|
-
controller.enqueue(new TextEncoder().encode(''));
|
|
296
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
297
|
-
controller.close();
|
|
298
|
-
}
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
const result = await MD5ReadableStream.hash(source);
|
|
302
|
-
|
|
303
|
-
expect(result.digest).toBe(md5Core(input));
|
|
304
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
305
|
-
}, 10000);
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
if (typeof Blob !== 'undefined') {
|
|
309
|
-
describe('hashBlob', () => {
|
|
310
|
-
test('should hash a Blob', async () => {
|
|
311
|
-
const input = 'blob hash test';
|
|
312
|
-
const blob = new Blob([input]);
|
|
313
|
-
|
|
314
|
-
const result = await hashBlob(blob);
|
|
315
|
-
|
|
316
|
-
expect(result.digest).toBe(md5Core(input));
|
|
317
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
318
|
-
}, 10000);
|
|
319
|
-
|
|
320
|
-
test('should hash an empty Blob', async () => {
|
|
321
|
-
const blob = new Blob([]);
|
|
322
|
-
|
|
323
|
-
const result = await hashBlob(blob);
|
|
324
|
-
|
|
325
|
-
expect(result.digest).toBe(md5Core(''));
|
|
326
|
-
expect(result.bytesProcessed).toBe(0);
|
|
327
|
-
}, 10000);
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
describe('integration', () => {
|
|
332
|
-
test('should handle large data correctly', async () => {
|
|
333
|
-
const chunkSize = 1024 * 1024; // 1MB
|
|
334
|
-
const numChunks = 3;
|
|
335
|
-
const totalBytes = chunkSize * numChunks;
|
|
336
|
-
|
|
337
|
-
const source = new ReadableStream({
|
|
338
|
-
start(controller) {
|
|
339
|
-
const chunk = new TextEncoder().encode('a'.repeat(chunkSize));
|
|
340
|
-
for (let i = 0; i < numChunks; i++) {
|
|
341
|
-
controller.enqueue(chunk);
|
|
342
|
-
}
|
|
343
|
-
controller.close();
|
|
344
|
-
}
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
const result = await MD5ReadableStream.hash(source);
|
|
348
|
-
|
|
349
|
-
// We're just testing that it processes the data without crashing
|
|
350
|
-
// The actual hash doesn't matter for this test
|
|
351
|
-
expect(result.bytesProcessed).toBe(totalBytes);
|
|
352
|
-
expect(result.digest.length).toBe(32); // MD5 is 32 hex chars
|
|
353
|
-
}, 10000);
|
|
354
|
-
});
|
|
355
|
-
}
|
|
@@ -1,335 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WHATWG Streams tests for browser environments
|
|
3
|
-
* These tests verify the WHATWG Streams implementation works correctly
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { MD5ReadableStream, hashReadableStream, createMD5ReadableStream, hashFile, hashBlob } from '../../src/stream/whatwg-stream.js';
|
|
7
|
-
import { md5Core } from '../../src/core/index.js';
|
|
8
|
-
|
|
9
|
-
describe('MD5ReadableStream', () => {
|
|
10
|
-
test('should compute MD5 hash for empty stream', async () => {
|
|
11
|
-
const source = new ReadableStream({
|
|
12
|
-
start(controller) {
|
|
13
|
-
controller.close();
|
|
14
|
-
}
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
const result = await MD5ReadableStream.hash(source);
|
|
18
|
-
|
|
19
|
-
expect(result.digest).toBe(md5Core(''));
|
|
20
|
-
expect(result.bytesProcessed).toBe(0);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test('should compute MD5 hash for simple string', async () => {
|
|
24
|
-
const input = 'hello';
|
|
25
|
-
const source = new ReadableStream({
|
|
26
|
-
start(controller) {
|
|
27
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
28
|
-
controller.close();
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
const result = await MD5ReadableStream.hash(source);
|
|
33
|
-
|
|
34
|
-
expect(result.digest).toBe(md5Core(input));
|
|
35
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test('should compute MD5 hash for longer string', async () => {
|
|
39
|
-
const input = 'a'.repeat(1000);
|
|
40
|
-
const source = new ReadableStream({
|
|
41
|
-
start(controller) {
|
|
42
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
43
|
-
controller.close();
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
const result = await MD5ReadableStream.hash(source);
|
|
48
|
-
|
|
49
|
-
expect(result.digest).toBe(md5Core(input));
|
|
50
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test('should process chunked data correctly', async () => {
|
|
54
|
-
const input = 'hello world';
|
|
55
|
-
const source = new ReadableStream({
|
|
56
|
-
start(controller) {
|
|
57
|
-
controller.enqueue(new TextEncoder().encode('hello '));
|
|
58
|
-
controller.enqueue(new TextEncoder().encode('world'));
|
|
59
|
-
controller.close();
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const result = await MD5ReadableStream.hash(source);
|
|
64
|
-
|
|
65
|
-
expect(result.digest).toBe(md5Core(input));
|
|
66
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
test('should handle multiple chunks of varying sizes', async () => {
|
|
70
|
-
const input = 'This is a test string with multiple chunks';
|
|
71
|
-
const chunks = ['This ', 'is a', ' test', ' string', ' with', ' multi', 'ple c', 'hunks'];
|
|
72
|
-
|
|
73
|
-
const source = new ReadableStream({
|
|
74
|
-
start(controller) {
|
|
75
|
-
chunks.forEach(chunk => controller.enqueue(new TextEncoder().encode(chunk)));
|
|
76
|
-
controller.close();
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
const result = await MD5ReadableStream.hash(source);
|
|
81
|
-
|
|
82
|
-
expect(result.digest).toBe(md5Core(input));
|
|
83
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
test('should handle data that exactly fills 64-byte blocks', async () => {
|
|
87
|
-
const input = 'a'.repeat(64);
|
|
88
|
-
const source = new ReadableStream({
|
|
89
|
-
start(controller) {
|
|
90
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
91
|
-
controller.close();
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
const result = await MD5ReadableStream.hash(source);
|
|
96
|
-
|
|
97
|
-
expect(result.digest).toBe(md5Core(input));
|
|
98
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
test('should handle data that is multiple of 64 bytes', async () => {
|
|
102
|
-
const input = 'a'.repeat(128);
|
|
103
|
-
const source = new ReadableStream({
|
|
104
|
-
start(controller) {
|
|
105
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
106
|
-
controller.close();
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
const result = await MD5ReadableStream.hash(source);
|
|
111
|
-
|
|
112
|
-
expect(result.digest).toBe(md5Core(input));
|
|
113
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
test('should handle special characters', async () => {
|
|
117
|
-
const input = '!@#$%^&*()_+-=[]{}|;:,.<>?';
|
|
118
|
-
const source = new ReadableStream({
|
|
119
|
-
start(controller) {
|
|
120
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
121
|
-
controller.close();
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
const result = await MD5ReadableStream.hash(source);
|
|
126
|
-
|
|
127
|
-
expect(result.digest).toBe(md5Core(input));
|
|
128
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
test('should emit bytesProcessed correctly', async () => {
|
|
132
|
-
const totalBytes = 256;
|
|
133
|
-
const chunkSize = 64;
|
|
134
|
-
|
|
135
|
-
const source = new ReadableStream({
|
|
136
|
-
start(controller) {
|
|
137
|
-
const chunk = new TextEncoder().encode('a'.repeat(chunkSize));
|
|
138
|
-
for (let i = 0; i < 4; i++) {
|
|
139
|
-
controller.enqueue(chunk);
|
|
140
|
-
}
|
|
141
|
-
controller.close();
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
const result = await MD5ReadableStream.hash(source);
|
|
146
|
-
|
|
147
|
-
expect(result.bytesProcessed).toBe(totalBytes);
|
|
148
|
-
expect(result.digest.length).toBe(32);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
test('should support factory function createMD5ReadableStream', async () => {
|
|
152
|
-
const input = 'factory test';
|
|
153
|
-
const source = new ReadableStream({
|
|
154
|
-
start(controller) {
|
|
155
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
156
|
-
controller.close();
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
const stream = createMD5ReadableStream(source);
|
|
161
|
-
const result = await stream.getResult();
|
|
162
|
-
|
|
163
|
-
expect(result.digest).toBe(md5Core(input));
|
|
164
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
test('should support custom add32 function', async () => {
|
|
168
|
-
const input = 'custom add32 test';
|
|
169
|
-
const source = new ReadableStream({
|
|
170
|
-
start(controller) {
|
|
171
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
172
|
-
controller.close();
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
const customAdd32 = (x: number, y: number) => (x + y) & 0xffffffff;
|
|
177
|
-
const result = await MD5ReadableStream.hash(source, { add32: customAdd32 });
|
|
178
|
-
|
|
179
|
-
expect(result.digest).toBe(md5Core(input));
|
|
180
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
test('should handle sequential processing', async () => {
|
|
184
|
-
const parts = ['Hello, ', 'World!', ' This is ', 'MD5 streaming.'];
|
|
185
|
-
const full = parts.join('');
|
|
186
|
-
|
|
187
|
-
const source = new ReadableStream({
|
|
188
|
-
start(controller) {
|
|
189
|
-
parts.forEach(part => controller.enqueue(new TextEncoder().encode(part)));
|
|
190
|
-
controller.close();
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
const result = await MD5ReadableStream.hash(source);
|
|
195
|
-
|
|
196
|
-
expect(result.digest).toBe(md5Core(full));
|
|
197
|
-
expect(result.bytesProcessed).toBe(full.length);
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
test('should handle single byte chunks', async () => {
|
|
201
|
-
const input = 'a';
|
|
202
|
-
const source = new ReadableStream({
|
|
203
|
-
start(controller) {
|
|
204
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
205
|
-
controller.close();
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
const result = await MD5ReadableStream.hash(source);
|
|
210
|
-
|
|
211
|
-
expect(result.digest).toBe(md5Core(input));
|
|
212
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
test('should emit valid hex digest', async () => {
|
|
216
|
-
const source = new ReadableStream({
|
|
217
|
-
start(controller) {
|
|
218
|
-
controller.enqueue(new TextEncoder().encode('test'));
|
|
219
|
-
controller.close();
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
const result = await MD5ReadableStream.hash(source);
|
|
224
|
-
|
|
225
|
-
// MD5 digest should be 32 hex characters
|
|
226
|
-
expect(result.digest).toMatch(/^[0-9a-f]{32}$/);
|
|
227
|
-
expect(result.digest.length).toBe(32);
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
test('should get current state during processing', async () => {
|
|
231
|
-
const source = new ReadableStream({
|
|
232
|
-
start(controller) {
|
|
233
|
-
controller.enqueue(new TextEncoder().encode('test'));
|
|
234
|
-
controller.close();
|
|
235
|
-
}
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
const stream = new MD5ReadableStream(source);
|
|
239
|
-
|
|
240
|
-
// Check initial state before reading
|
|
241
|
-
const initialState = stream.getCurrentState();
|
|
242
|
-
expect(initialState.state).toHaveLength(4);
|
|
243
|
-
expect(initialState.bytesProcessed).toBe(0);
|
|
244
|
-
|
|
245
|
-
// Read some data
|
|
246
|
-
const reader = stream.getReader();
|
|
247
|
-
await reader.read();
|
|
248
|
-
|
|
249
|
-
// Check state after reading
|
|
250
|
-
const afterDataState = stream.getCurrentState();
|
|
251
|
-
expect(afterDataState.bytesProcessed).toBe(4);
|
|
252
|
-
|
|
253
|
-
// Check bytes processed getter
|
|
254
|
-
expect(stream.getBytesProcessed()).toBe(4);
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
test('should handle empty chunks', async () => {
|
|
258
|
-
const input = 'test';
|
|
259
|
-
const source = new ReadableStream({
|
|
260
|
-
start(controller) {
|
|
261
|
-
controller.enqueue(new TextEncoder().encode(''));
|
|
262
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
263
|
-
controller.close();
|
|
264
|
-
}
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
const result = await MD5ReadableStream.hash(source);
|
|
268
|
-
|
|
269
|
-
expect(result.digest).toBe(md5Core(input));
|
|
270
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
271
|
-
});
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
describe('hashReadableStream', () => {
|
|
275
|
-
test('should hash a ReadableStream', async () => {
|
|
276
|
-
const input = 'hash readable stream test';
|
|
277
|
-
const source = new ReadableStream({
|
|
278
|
-
start(controller) {
|
|
279
|
-
controller.enqueue(new TextEncoder().encode(input));
|
|
280
|
-
controller.close();
|
|
281
|
-
}
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
const result = await hashReadableStream(source);
|
|
285
|
-
|
|
286
|
-
expect(result.digest).toBe(md5Core(input));
|
|
287
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
288
|
-
});
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
describe('hashBlob', () => {
|
|
292
|
-
test('should hash a Blob', async () => {
|
|
293
|
-
const input = 'blob hash test';
|
|
294
|
-
const blob = new Blob([input]);
|
|
295
|
-
|
|
296
|
-
const result = await hashBlob(blob);
|
|
297
|
-
|
|
298
|
-
expect(result.digest).toBe(md5Core(input));
|
|
299
|
-
expect(result.bytesProcessed).toBe(input.length);
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
test('should hash an empty Blob', async () => {
|
|
303
|
-
const blob = new Blob([]);
|
|
304
|
-
|
|
305
|
-
const result = await hashBlob(blob);
|
|
306
|
-
|
|
307
|
-
expect(result.digest).toBe(md5Core(''));
|
|
308
|
-
expect(result.bytesProcessed).toBe(0);
|
|
309
|
-
});
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
describe('integration', () => {
|
|
313
|
-
test('should handle large data correctly', async () => {
|
|
314
|
-
const chunkSize = 1024 * 1024; // 1MB
|
|
315
|
-
const numChunks = 3;
|
|
316
|
-
const totalBytes = chunkSize * numChunks;
|
|
317
|
-
|
|
318
|
-
const source = new ReadableStream({
|
|
319
|
-
start(controller) {
|
|
320
|
-
const chunk = new TextEncoder().encode('a'.repeat(chunkSize));
|
|
321
|
-
for (let i = 0; i < numChunks; i++) {
|
|
322
|
-
controller.enqueue(chunk);
|
|
323
|
-
}
|
|
324
|
-
controller.close();
|
|
325
|
-
}
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
const result = await MD5ReadableStream.hash(source);
|
|
329
|
-
|
|
330
|
-
// We're just testing that it processes the data without crashing
|
|
331
|
-
// The actual hash doesn't matter for this test
|
|
332
|
-
expect(result.bytesProcessed).toBe(totalBytes);
|
|
333
|
-
expect(result.digest.length).toBe(32); // MD5 is 32 hex chars
|
|
334
|
-
});
|
|
335
|
-
});
|