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.
Files changed (177) hide show
  1. package/README.md +38 -24
  2. package/dist/adapters/ie11.cjs +1 -2
  3. package/dist/adapters/ie11.js +1 -2
  4. package/dist/adapters/node.cjs +1 -2
  5. package/dist/adapters/node.js +1 -2
  6. package/dist/adapters/webcrypto.cjs +1 -2
  7. package/dist/adapters/webcrypto.js +1 -2
  8. package/dist/index.cjs +1 -2
  9. package/dist/index.d.ts +149 -5
  10. package/dist/index.js +3 -2
  11. package/dist/md5.cjs +1 -0
  12. package/dist/md5.d.ts +20 -0
  13. package/dist/md5.js +1 -0
  14. package/dist/stream/md5-stream.cjs +1 -2
  15. package/dist/stream/md5-stream.js +1 -2
  16. package/dist/stream/whatwg-stream.cjs +1 -2
  17. package/dist/stream/whatwg-stream.js +1 -2
  18. package/dist/utils/detect.cjs +1 -2
  19. package/dist/utils/detect.js +3 -2
  20. package/package.json +10 -15
  21. package/pure-md5-0.2.1.tgz +0 -0
  22. package/test-tree-shake.mjs +12 -0
  23. package/.aliases +0 -19
  24. package/.bash_profile +0 -12
  25. package/.bash_prompt +0 -56
  26. package/.changeset/README.md +0 -32
  27. package/.changeset/config.json +0 -16
  28. package/.continue/mcpServers/new-mcp-server.yaml +0 -10
  29. package/.continue/rules +0 -29
  30. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -35
  31. package/.github/ISSUE_TEMPLATE/documentation.md +0 -20
  32. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  33. package/.github/PULL_REQUEST_TEMPLATE.md +0 -35
  34. package/.github/workflows/npm-publish.yml +0 -33
  35. package/.github/workflows/release.yml +0 -42
  36. package/CHANGELOG.md +0 -9
  37. package/CONTRIBUTING.md +0 -203
  38. package/MIGRATION_GUIDE_STREAMS.md +0 -374
  39. package/STREAM_API.md +0 -582
  40. package/STREAM_BENCHMARKS.md +0 -232
  41. package/STREAM_EXAMPLES.md +0 -669
  42. package/STREAM_OPTIMIZATION_REPORT.md +0 -136
  43. package/STREAM_TROUBLESHOOTING.md +0 -537
  44. package/WEB_CRYPTO_TESTS_SUMMARY.md +0 -140
  45. package/WHATWG_STREAMS.md +0 -191
  46. package/__tests__/adapters/node-crypto.test.ts +0 -167
  47. package/__tests__/adapters/web-crypto-node.test.ts +0 -73
  48. package/__tests__/adapters/web-crypto.test.ts +0 -195
  49. package/__tests__/add32.test.ts +0 -33
  50. package/__tests__/fallback.test.ts +0 -345
  51. package/__tests__/hex.test.ts +0 -38
  52. package/__tests__/hex_chr.test.ts +0 -20
  53. package/__tests__/index.test.ts +0 -87
  54. package/__tests__/integration/fixtures/test-file.txt +0 -1
  55. package/__tests__/integration/md5-stream-file.test.ts +0 -293
  56. package/__tests__/integration/node-crypto-file.test.ts +0 -86
  57. package/__tests__/integration/web-crypto.test.ts +0 -38
  58. package/__tests__/md51.test.ts +0 -73
  59. package/__tests__/md5block.test.ts +0 -61
  60. package/__tests__/md5cycle.test.ts +0 -48
  61. package/__tests__/round-functions.test.ts +0 -87
  62. package/__tests__/stream/fs-utils.test.ts +0 -209
  63. package/__tests__/stream/md5-stream-edge-cases.test.ts +0 -461
  64. package/__tests__/stream/md5-stream.test.ts +0 -418
  65. package/__tests__/stream/whatwg-stream.test.ts +0 -355
  66. package/__tests__/stream/whatwg-stream.test.ts.bak2 +0 -335
  67. package/benchmarks/md5-stream.bench.ts +0 -212
  68. package/benchmarks/whatwg-stream.bench.ts +0 -180
  69. package/dist/adapters/ie11.cjs.map +0 -1
  70. package/dist/adapters/ie11.js.map +0 -1
  71. package/dist/adapters/node.cjs.map +0 -1
  72. package/dist/adapters/node.js.map +0 -1
  73. package/dist/adapters/webcrypto.cjs.map +0 -1
  74. package/dist/adapters/webcrypto.js.map +0 -1
  75. package/dist/chunk-2YXXFGBV.js +0 -2
  76. package/dist/chunk-2YXXFGBV.js.map +0 -1
  77. package/dist/chunk-4KSCMS4Q.js +0 -2
  78. package/dist/chunk-4KSCMS4Q.js.map +0 -1
  79. package/dist/chunk-6P2QV5SR.js +0 -4
  80. package/dist/chunk-6P2QV5SR.js.map +0 -1
  81. package/dist/chunk-G5WHEAIQ.js +0 -2
  82. package/dist/chunk-G5WHEAIQ.js.map +0 -1
  83. package/dist/chunk-H2K353LR.js +0 -2
  84. package/dist/chunk-H2K353LR.js.map +0 -1
  85. package/dist/chunk-JKVD5LHZ.js +0 -2
  86. package/dist/chunk-JKVD5LHZ.js.map +0 -1
  87. package/dist/chunk-NWQ4N5RX.js +0 -2
  88. package/dist/chunk-NWQ4N5RX.js.map +0 -1
  89. package/dist/chunk-PHZ7FTYF.js +0 -2
  90. package/dist/chunk-PHZ7FTYF.js.map +0 -1
  91. package/dist/chunk-PNZTVQA7.js +0 -2
  92. package/dist/chunk-PNZTVQA7.js.map +0 -1
  93. package/dist/chunk-R4JB5MBR.js +0 -2
  94. package/dist/chunk-R4JB5MBR.js.map +0 -1
  95. package/dist/chunk-VFOAY6XI.js +0 -2
  96. package/dist/chunk-VFOAY6XI.js.map +0 -1
  97. package/dist/chunk-XB5BQIEX.js +0 -2
  98. package/dist/chunk-XB5BQIEX.js.map +0 -1
  99. package/dist/core/index.cjs +0 -2
  100. package/dist/core/index.cjs.map +0 -1
  101. package/dist/core/index.d.cts +0 -19
  102. package/dist/core/index.d.ts +0 -19
  103. package/dist/core/index.js +0 -2
  104. package/dist/core/index.js.map +0 -1
  105. package/dist/index.cjs.map +0 -1
  106. package/dist/index.d.cts +0 -84
  107. package/dist/index.js.map +0 -1
  108. package/dist/stream/adapter.cjs +0 -2
  109. package/dist/stream/adapter.cjs.map +0 -1
  110. package/dist/stream/adapter.d.cts +0 -63
  111. package/dist/stream/adapter.d.ts +0 -63
  112. package/dist/stream/adapter.js +0 -2
  113. package/dist/stream/adapter.js.map +0 -1
  114. package/dist/stream/fs-utils.cjs +0 -2
  115. package/dist/stream/fs-utils.cjs.map +0 -1
  116. package/dist/stream/fs-utils.d.cts +0 -137
  117. package/dist/stream/fs-utils.d.ts +0 -137
  118. package/dist/stream/fs-utils.js +0 -2
  119. package/dist/stream/fs-utils.js.map +0 -1
  120. package/dist/stream/index.cjs +0 -2
  121. package/dist/stream/index.cjs.map +0 -1
  122. package/dist/stream/index.d.cts +0 -4
  123. package/dist/stream/index.d.ts +0 -4
  124. package/dist/stream/index.js +0 -2
  125. package/dist/stream/index.js.map +0 -1
  126. package/dist/stream/light/index.cjs +0 -2
  127. package/dist/stream/light/index.cjs.map +0 -1
  128. package/dist/stream/light/index.d.cts +0 -4
  129. package/dist/stream/light/index.d.ts +0 -4
  130. package/dist/stream/light/index.js +0 -2
  131. package/dist/stream/light/index.js.map +0 -1
  132. package/dist/stream/md5-stream.cjs.map +0 -1
  133. package/dist/stream/md5-stream.js.map +0 -1
  134. package/dist/stream/whatwg-stream.cjs.map +0 -1
  135. package/dist/stream/whatwg-stream.js.map +0 -1
  136. package/dist/types-edGoGJ5V.d.cts +0 -42
  137. package/dist/types-edGoGJ5V.d.ts +0 -42
  138. package/dist/utils/detect.cjs.map +0 -1
  139. package/dist/utils/detect.js.map +0 -1
  140. package/planning/03-optimization-size-tree-shaking/01-es-modules-tree-shaking.md +0 -152
  141. package/planning/03-optimization-size-tree-shaking/02-consolidate-modules.md +0 -65
  142. package/planning/03-optimization-size-tree-shaking/03-remove-duplicate-add32.md +0 -93
  143. package/planning/03-optimization-size-tree-shaking/04-remove-runtime-check.md +0 -102
  144. package/planning/03-optimization-size-tree-shaking/05-optimize-loops-performance.md +0 -107
  145. package/planning/03-optimization-size-tree-shaking/06-tsup-formats-configuration.md +0 -227
  146. package/planning/03-optimization-size-tree-shaking/07-multiple-build-formats.md +0 -228
  147. package/planning/03-optimization-size-tree-shaking/08-benchmarks-metrics.md +0 -34
  148. package/planning/03-optimization-size-tree-shaking/MIGRATION_GUIDE.md +0 -260
  149. package/planning/03-optimization-size-tree-shaking/README.md +0 -173
  150. package/planning/03-optimization-size-tree-shaking/SUMMARY.md +0 -168
  151. package/planning/04-adapter-backend/03-backend-web-crypto.md +0 -149
  152. package/planning/04-adapter-backend/04-backend-node-crypto.md +0 -181
  153. package/planning/04-adapter-backend/05-backend-pure-js.md +0 -174
  154. package/planning/04-adapter-backend/06-backend-ie11.md +0 -158
  155. package/planning/04-adapter-backend/07-detection-environment.md +0 -232
  156. package/planning/04-adapter-backend/08-detection-backend.md +0 -210
  157. package/planning/04-adapter-backend/09-adapter-unified.md +0 -255
  158. package/planning/04-adapter-backend/10-fallback-mechanism.md +0 -333
  159. package/planning/04-adapter-backend/11-tests-backend-web-crypto.md +0 -191
  160. package/planning/04-adapter-backend/12-tests-backend-node-crypto.md +0 -222
  161. package/planning/04-adapter-backend/README.md +0 -45
  162. package/planning/05-documentation-publishing/01-README-optimization.md +0 -105
  163. package/planning/05-documentation-publishing/02-VitePress-site-evaluation.md +0 -136
  164. package/planning/05-documentation-publishing/03-Changeset-setup.md +0 -192
  165. package/planning/05-documentation-publishing/04-GitHub-templates.md +0 -252
  166. package/planning/05-documentation-publishing/README.md +0 -22
  167. package/planning/05-documentation-publishing/STATUS.md +0 -222
  168. package/planning/prd.md +0 -405
  169. package/planning/streams/01-create-md5stream-class.md +0 -69
  170. package/planning/streams/02-create-factory-api.md +0 -65
  171. package/planning/streams/03-fs-integration.md +0 -37
  172. package/planning/streams/04-whatwg-streams-support.md +0 -37
  173. package/planning/streams/05-audit-optimization.md +0 -121
  174. package/planning/streams/06-comprehensive-tests-docs.md +0 -137
  175. package/planning/streams/07-architecture-integration.md +0 -38
  176. package/planning/streams/README.md +0 -98
  177. package/tsup.config.ts +0 -24
@@ -1,87 +0,0 @@
1
- import { md5 } from '../src/index';
2
-
3
- describe('md5', () => {
4
- // Test vectors from RFC 1321
5
- test('should compute correct MD5 hash for RFC 1321 test vectors', () => {
6
- // Test 1: empty string
7
- expect(md5('')).toBe('d41d8cd98f00b204e9800998ecf8427e');
8
-
9
- // Test 2: "a"
10
- expect(md5('a')).toBe('0cc175b9c0f1b6a831c399e269772661');
11
-
12
- // Test 3: "abc"
13
- expect(md5('abc')).toBe('900150983cd24fb0d6963f7d28e17f72');
14
-
15
- // Test 4: "message digest"
16
- expect(md5('message digest')).toBe('f96b697d7cb7938d525a2f31aaf161d0');
17
-
18
- // Test 5: "abcdefghijklmnopqrstuvwxyz"
19
- expect(md5('abcdefghijklmnopqrstuvwxyz')).toBe(
20
- 'c3fcd3d76192e4007dfb496cca67e13b'
21
- );
22
-
23
- // Test 6: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
24
- expect(
25
- md5('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
26
- ).toBe('d174ab98d277d9f5a5611c2c9f419d9f');
27
-
28
- // Test 7: "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
29
- expect(
30
- md5(
31
- '12345678901234567890123456789012345678901234567890123456789012345678901234567890'
32
- )
33
- ).toBe('57edf4a22be3c955ac49da2e2107b67a');
34
- });
35
-
36
- test('should compute correct MD5 hash for common strings', () => {
37
- // Test from the code itself
38
- expect(md5('hello')).toBe('5d41402abc4b2a76b9719d911017c592');
39
-
40
- // Additional common test cases
41
- expect(md5('Hello, World!')).toBe('65a8e27d8879283831b664bd8b7f0ad4');
42
- expect(md5('The quick brown fox jumps over the lazy dog')).toBe(
43
- '9e107d9d372bb6826bd81d3542a419d6'
44
- );
45
- expect(md5('The quick brown fox jumps over the lazy dog.')).toBe(
46
- 'e4d909c290d0fb1ca068ffaddf22cbd0'
47
- );
48
- });
49
-
50
- test('should handle edge cases', () => {
51
- // Very long string
52
- const longString = 'x'.repeat(10000);
53
- const hash = md5(longString);
54
- expect(hash).toMatch(/^[0-9a-f]{32}$/);
55
-
56
- // Single character
57
- expect(md5('x')).toBe('9dd4e461268c8034f5c8564e155c67a6');
58
-
59
- // String with null bytes
60
- expect(md5('test\0null')).toBe('530923740caad7aad6a2cd4b894d983d');
61
- });
62
-
63
- test('should produce consistent results', () => {
64
- const input = 'test string';
65
- const hash1 = md5(input);
66
- const hash2 = md5(input);
67
- const hash3 = md5(input);
68
-
69
- expect(hash1).toBe(hash2);
70
- expect(hash2).toBe(hash3);
71
- expect(hash1).toMatch(/^[0-9a-f]{32}$/);
72
- });
73
-
74
- test('should handle Unicode strings (using UTF-16 code units)', () => {
75
- // Note: This implementation uses charCodeAt() which returns UTF-16 code units
76
- // This is different from UTF-8 encoding used by some other MD5 implementations
77
- expect(md5('🎉')).toBe('801c2a6dbe01c0c530a03a5f5f5b1214');
78
- expect(md5('Привет мир')).toBe('5abca3326cf0cefc00efe7065b5e0cf6'); // "Hello world" in Russian
79
- });
80
-
81
- test('should verify the built-in check works', () => {
82
- // The function has a built-in check for 'hello'
83
- // This ensures the runtime check doesn't break functionality
84
- const result = md5('hello');
85
- expect(result).toBe('5d41402abc4b2a76b9719d911017c592');
86
- });
87
- });
@@ -1 +0,0 @@
1
- Hello, World!
@@ -1,293 +0,0 @@
1
- /**
2
- * Integration tests for MD5Stream with real file I/O
3
- */
4
-
5
- import fs from 'fs';
6
- import path from 'path';
7
- import { MD5Stream, hashFile, hashFileSync, verifyFile, hashFileDigest } from '../../src/stream/index.js';
8
- import { md5Core } from '../../src/core/index.js';
9
-
10
- describe('MD5Stream - File I/O Integration', () => {
11
- let tempDir: string;
12
-
13
- beforeAll(() => {
14
- tempDir = path.join(__dirname, 'temp');
15
- if (!fs.existsSync(tempDir)) {
16
- fs.mkdirSync(tempDir, { recursive: true });
17
- }
18
- });
19
-
20
- afterAll(() => {
21
- // Cleanup temp files
22
- if (fs.existsSync(tempDir)) {
23
- const files = fs.readdirSync(tempDir);
24
- files.forEach(file => {
25
- const filePath = path.join(tempDir, file);
26
- if (fs.existsSync(filePath)) {
27
- fs.unlinkSync(filePath);
28
- }
29
- });
30
- fs.rmdirSync(tempDir);
31
- }
32
- });
33
-
34
- describe('hashFile (async)', () => {
35
- test('should hash a small text file', async () => {
36
- const filePath = path.join(tempDir, 'test-small.txt');
37
- const content = 'Hello, World!';
38
- fs.writeFileSync(filePath, content);
39
-
40
- const result = await hashFile(filePath);
41
-
42
- expect(result.digest).toBe(md5Core(content));
43
- expect(result.bytesProcessed).toBe(content.length);
44
- expect(result.digest.length).toBe(32);
45
- });
46
-
47
- test('should hash an empty file', async () => {
48
- const filePath = path.join(tempDir, 'test-empty.txt');
49
- fs.writeFileSync(filePath, '');
50
-
51
- const result = await hashFile(filePath);
52
-
53
- expect(result.digest).toBe(md5Core(''));
54
- expect(result.bytesProcessed).toBe(0);
55
- });
56
-
57
- test('should handle file path as string', async () => {
58
- const filePath = path.join(tempDir, 'test-path.txt');
59
- const content = 'Path test content';
60
- fs.writeFileSync(filePath, content);
61
-
62
- const result = await hashFile(filePath);
63
-
64
- expect(result.digest).toBe(md5Core(content));
65
- });
66
-
67
- test('should handle large files efficiently', async () => {
68
- const filePath = path.join(tempDir, 'test-large.bin');
69
- const size = 10 * 1024 * 1024; // 10MB
70
- const content = 'a'.repeat(size);
71
- fs.writeFileSync(filePath, content);
72
-
73
- const start = Date.now();
74
- const result = await hashFile(filePath);
75
- const duration = Date.now() - start;
76
-
77
- expect(result.bytesProcessed).toBe(size);
78
- expect(result.digest.length).toBe(32);
79
- expect(duration).toBeLessThan(5000); // Should complete in under 5 seconds
80
- }, 10000);
81
- });
82
-
83
- describe('hashFileSync (sync)', () => {
84
- test('should hash a small file synchronously', () => {
85
- const filePath = path.join(tempDir, 'test-sync.txt');
86
- const content = 'Sync hash test';
87
- fs.writeFileSync(filePath, content);
88
-
89
- const digest = hashFileSync(filePath);
90
-
91
- expect(digest).toBe(md5Core(content));
92
- expect(digest.length).toBe(32);
93
- });
94
-
95
- test('should hash empty file synchronously', () => {
96
- const filePath = path.join(tempDir, 'test-sync-empty.txt');
97
- fs.writeFileSync(filePath, '');
98
-
99
- const digest = hashFileSync(filePath);
100
-
101
- expect(digest).toBe(md5Core(''));
102
- });
103
-
104
- test('should be faster than async for small files', () => {
105
- const filePath = path.join(tempDir, 'test-sync-performance.txt');
106
- const content = 'a'.repeat(1000);
107
- fs.writeFileSync(filePath, content);
108
-
109
- const startSync = Date.now();
110
- hashFileSync(filePath);
111
- const syncDuration = Date.now() - startSync;
112
-
113
- expect(syncDuration).toBeLessThan(100); // Sync should be fast for small files
114
- });
115
- });
116
-
117
- describe('hashFileDigest', () => {
118
- test('should return only digest string', async () => {
119
- const filePath = path.join(tempDir, 'test-digest.txt');
120
- const content = 'Digest only test';
121
- fs.writeFileSync(filePath, content);
122
-
123
- const digest = await hashFileDigest(filePath);
124
-
125
- expect(typeof digest).toBe('string');
126
- expect(digest).toBe(md5Core(content));
127
- expect(digest.length).toBe(32);
128
- });
129
- });
130
-
131
- describe('verifyFile', () => {
132
- test('should verify correct hash', async () => {
133
- const filePath = path.join(tempDir, 'test-verify.txt');
134
- const content = 'Verification test';
135
- const correctDigest = md5Core(content);
136
- fs.writeFileSync(filePath, content);
137
-
138
- const isVerified = await verifyFile(filePath, correctDigest);
139
-
140
- expect(isVerified).toBe(true);
141
- });
142
-
143
- test('should reject incorrect hash', async () => {
144
- const filePath = path.join(tempDir, 'test-verify-wrong.txt');
145
- const content = 'Verification test wrong';
146
- const wrongDigest = '00000000000000000000000000000000';
147
- fs.writeFileSync(filePath, content);
148
-
149
- const isVerified = await verifyFile(filePath, wrongDigest);
150
-
151
- expect(isVerified).toBe(false);
152
- });
153
-
154
- test('should handle file not found', async () => {
155
- const filePath = path.join(tempDir, 'test-verify-not-found.txt');
156
- const digest = '00000000000000000000000000000000';
157
-
158
- await expect(verifyFile(filePath, digest)).rejects.toThrow();
159
- });
160
- });
161
-
162
- describe('MD5Stream with file streams', () => {
163
- test('should hash file using fs.createReadStream', (done) => {
164
- const filePath = path.join(tempDir, 'test-stream.txt');
165
- const content = 'Stream file test';
166
- fs.writeFileSync(filePath, content);
167
-
168
- const stream = new MD5Stream();
169
-
170
- stream.on('md5', (result) => {
171
- expect(result.digest).toBe(md5Core(content));
172
- expect(result.bytesProcessed).toBe(content.length);
173
- done();
174
- });
175
-
176
- fs.createReadStream(filePath).pipe(stream);
177
- });
178
-
179
- test('should handle file stream errors gracefully', (done) => {
180
- const stream = new MD5Stream();
181
-
182
- const source = fs.createReadStream('/nonexistent/file.txt');
183
-
184
- // Source stream will emit error, but it should not hang
185
- source.on('error', (error) => {
186
- // Error is on source stream, not MD5Stream
187
- // This is expected behavior - the source stream emits the error
188
- expect(error).toBeDefined();
189
- done();
190
- });
191
-
192
- // MD5Stream will just see end-of-stream since source fails early
193
- stream.on('md5', () => {
194
- // This shouldn't happen for non-existent file
195
- done();
196
- });
197
-
198
- source.pipe(stream);
199
- });
200
- });
201
-
202
- describe('Progress tracking', () => {
203
- test('should support progress callback', (done) => {
204
- const filePath = path.join(tempDir, 'test-progress.txt');
205
- const content = 'a'.repeat(10000);
206
- fs.writeFileSync(filePath, content);
207
-
208
- // Note: Current implementation doesn't have built-in progress
209
- // This is a placeholder for future implementation
210
- // For now, we just verify the file can be hashed
211
- hashFile(filePath).then((result) => {
212
- expect(result.bytesProcessed).toBe(content.length);
213
- done();
214
- });
215
- });
216
- });
217
-
218
- describe('Edge Cases', () => {
219
- test('should handle special characters in filename', async () => {
220
- const specialFileName = 'test with spaces & special!@#.txt';
221
- const filePath = path.join(tempDir, specialFileName);
222
- const content = 'Special filename test';
223
- fs.writeFileSync(filePath, content);
224
-
225
- const result = await hashFile(filePath);
226
-
227
- expect(result.digest).toBe(md5Core(content));
228
-
229
- // Cleanup
230
- if (fs.existsSync(filePath)) {
231
- fs.unlinkSync(filePath);
232
- }
233
- });
234
-
235
- test('should handle binary file content', async () => {
236
- const filePath = path.join(tempDir, 'test-binary.bin');
237
- const content = Buffer.alloc(100);
238
- for (let i = 0; i < 100; i++) {
239
- content[i] = i % 256;
240
- }
241
- fs.writeFileSync(filePath, content);
242
-
243
- const result = await hashFile(filePath);
244
-
245
- expect(result.digest.length).toBe(32);
246
- expect(result.bytesProcessed).toBe(100);
247
- });
248
-
249
- test('should handle unicode filename', async () => {
250
- const specialFileName = 'тест unicode 文件.txt';
251
- const filePath = path.join(tempDir, specialFileName);
252
- const content = 'Unicode filename test';
253
- fs.writeFileSync(filePath, content);
254
-
255
- const result = await hashFile(filePath);
256
-
257
- expect(result.digest).toBe(md5Core(content));
258
-
259
- // Cleanup
260
- if (fs.existsSync(filePath)) {
261
- fs.unlinkSync(filePath);
262
- }
263
- });
264
- });
265
-
266
- describe('Consistency', () => {
267
- test('should produce same hash for same file', async () => {
268
- const filePath = path.join(tempDir, 'test-consistency.txt');
269
- const content = 'Consistency test';
270
- fs.writeFileSync(filePath, content);
271
-
272
- const result1 = await hashFile(filePath);
273
- const result2 = await hashFile(filePath);
274
- const result3 = await hashFile(filePath);
275
-
276
- expect(result1.digest).toBe(result2.digest);
277
- expect(result2.digest).toBe(result3.digest);
278
- });
279
-
280
- test('should produce different hashes for different files', async () => {
281
- const file1Path = path.join(tempDir, 'test-diff1.txt');
282
- const file2Path = path.join(tempDir, 'test-diff2.txt');
283
-
284
- fs.writeFileSync(file1Path, 'Content 1');
285
- fs.writeFileSync(file2Path, 'Content 2');
286
-
287
- const result1 = await hashFile(file1Path);
288
- const result2 = await hashFile(file2Path);
289
-
290
- expect(result1.digest).not.toBe(result2.digest);
291
- });
292
- });
293
- });
@@ -1,86 +0,0 @@
1
- /**
2
- * Integration tests for Node.js Crypto Backend with files
3
- */
4
-
5
- import fs from 'fs';
6
- import path from 'path';
7
- import { NodeCryptoBackend } from '../../src/adapters/node.js';
8
-
9
- describe('NodeCryptoBackend with Files', () => {
10
- let backend: NodeCryptoBackend;
11
-
12
- beforeAll(() => {
13
- if (!NodeCryptoBackend.isAvailable()) {
14
- console.log('Node.js Crypto not available, skipping tests');
15
- pending('Node.js Crypto not available');
16
- return;
17
- }
18
- backend = new NodeCryptoBackend();
19
- });
20
-
21
- it('should hash a file', async () => {
22
- if (!backend) {
23
- pending('Node.js Crypto not available');
24
- return;
25
- }
26
-
27
- const filePath = path.join(__dirname, 'fixtures', 'test-file.txt');
28
-
29
- if (!fs.existsSync(filePath)) {
30
- console.log('Test file not found, creating it');
31
- const fixturesDir = path.dirname(filePath);
32
- if (!fs.existsSync(fixturesDir)) {
33
- fs.mkdirSync(fixturesDir, { recursive: true });
34
- }
35
- fs.writeFileSync(filePath, 'Hello, World!');
36
- }
37
-
38
- const content = fs.readFileSync(filePath);
39
- const result = await backend.hashBinary(content);
40
- expect(result.length).toBe(32);
41
- });
42
-
43
- it('should handle large files efficiently', async () => {
44
- if (!backend) {
45
- pending('Node.js Crypto not available');
46
- return;
47
- }
48
-
49
- const filePath = path.join(__dirname, 'fixtures', 'large-file.bin');
50
-
51
- if (!fs.existsSync(filePath)) {
52
- console.log('Large file not found, skipping');
53
- return;
54
- }
55
-
56
- const content = fs.readFileSync(filePath);
57
- const start = Date.now();
58
- const result = await backend.hashBinary(content);
59
- const duration = Date.now() - start;
60
-
61
- expect(result.length).toBe(32);
62
- expect(duration).toBeLessThan(500);
63
- });
64
-
65
- it('should produce consistent hash for the same file', async () => {
66
- if (!backend) {
67
- pending('Node.js Crypto not available');
68
- return;
69
- }
70
-
71
- const filePath = path.join(__dirname, 'fixtures', 'test-file.txt');
72
-
73
- if (!fs.existsSync(filePath)) {
74
- const fixturesDir = path.dirname(filePath);
75
- if (!fs.existsSync(fixturesDir)) {
76
- fs.mkdirSync(fixturesDir, { recursive: true });
77
- }
78
- fs.writeFileSync(filePath, 'Consistent Test Data');
79
- }
80
-
81
- const content = fs.readFileSync(filePath);
82
- const result1 = await backend.hashBinary(content);
83
- const result2 = await backend.hashBinary(content);
84
- expect(result1).toBe(result2);
85
- });
86
- });
@@ -1,38 +0,0 @@
1
- /**
2
- * Integration tests for Web Crypto Backend
3
- */
4
-
5
- import { md5, md5Adapter, getAllAvailableBackends } from '../../src/index';
6
-
7
- describe('WebCrypto Backend Integration', () => {
8
- describe('md5 function', () => {
9
- it('should use default backend correctly', async () => {
10
- const result = await md5('hello');
11
- expect(result).toBe('5d41402abc4b2a76b9719d911017c592');
12
- });
13
-
14
- it('should handle empty string', async () => {
15
- const result = await md5('');
16
- expect(result).toBe('d41d8cd98f00b204e9800998ecf8427e');
17
- });
18
-
19
- it('should handle unicode', async () => {
20
- const result = await md5('Привет мир');
21
- expect(result).toBe('5abca3326cf0cefc00efe7065b5e0cf6');
22
- });
23
- });
24
-
25
- describe('Backend availability', () => {
26
- it('should detect available backends', async () => {
27
- const available = await getAllAvailableBackends();
28
- expect(Array.isArray(available)).toBe(true);
29
- expect(available.length).toBeGreaterThan(0);
30
- });
31
-
32
- it('should use md5Adapter with webcrypto', async () => {
33
- // Check if WebCrypto is available
34
- const webcryptoAvailable = (md5Adapter as any).createBackendByName('webcrypto');
35
- expect(webcryptoAvailable).toBeDefined();
36
- });
37
- });
38
- });
@@ -1,73 +0,0 @@
1
- import md51 from '../src/md51';
2
-
3
- describe('md51', () => {
4
- test('should compute MD5 hash for empty string', () => {
5
- const result = md51('');
6
-
7
- // MD5 of empty string: d41d8cd98f00b204e9800998ecf8427e
8
- // In little-endian words: [0xd98cd41d, 0x04b2008f, 0x980099e9, 0x7e42f8ec]
9
- // But let's just verify it produces 4 numbers
10
- expect(result).toHaveLength(4);
11
- result.forEach((val) => {
12
- expect(Number.isInteger(val)).toBe(true);
13
- });
14
- });
15
-
16
- test('should compute MD5 hash for "hello"', () => {
17
- const result = md51('hello');
18
-
19
- // MD5 of "hello": 5d41402abc4b2a76b9719d911017c592
20
- // In little-endian words: [0x2a40415d, 0x762a4bbc, 0x9d71b9b9, 0x92c51701]
21
- expect(result).toHaveLength(4);
22
-
23
- // Convert to hex and verify
24
- const hexResult = result
25
- .map((n) => (n >>> 0).toString(16).padStart(8, '0'))
26
- .join('');
27
- // Note: the hex function reverses byte order, so we need to account for that
28
- // For now, just verify we get consistent results
29
- expect(hexResult).toBeDefined();
30
- });
31
-
32
- test('should handle strings longer than 64 characters', () => {
33
- const longString = 'a'.repeat(100);
34
- const result = md51(longString);
35
-
36
- expect(result).toHaveLength(4);
37
- result.forEach((val) => {
38
- expect(Number.isInteger(val)).toBe(true);
39
- });
40
- });
41
-
42
- test('should handle strings exactly 64 characters', () => {
43
- const exact64 = 'a'.repeat(64);
44
- const result = md51(exact64);
45
-
46
- expect(result).toHaveLength(4);
47
- });
48
-
49
- test('should handle custom add32 functions', () => {
50
- const customAdd32 = (x: number, y: number) => (x + y) & 0xffffffff;
51
- const result = md51('test', customAdd32);
52
-
53
- expect(result).toHaveLength(4);
54
- });
55
-
56
- test('should handle strings with special characters', () => {
57
- const testCases = [
58
- 'Hello, World!',
59
- '1234567890',
60
- '!@#$%^&*()',
61
- 'Привет мир', // Cyrillic text
62
- '\n\t\r' // Control characters
63
- ];
64
-
65
- testCases.forEach((input) => {
66
- const result = md51(input);
67
- expect(result).toHaveLength(4);
68
- result.forEach((val) => {
69
- expect(Number.isInteger(val)).toBe(true);
70
- });
71
- });
72
- });
73
- });
@@ -1,61 +0,0 @@
1
- import md5blk from '../src/md5blk';
2
-
3
- describe('md5blk', () => {
4
- test('should convert string to 16-word block', () => {
5
- // Test with a simple string
6
- const input = 'a'.repeat(64); // 64 characters = 1 full block
7
- const result = md5blk(input);
8
-
9
- expect(result).toHaveLength(16);
10
-
11
- // The character 'a' has code 97
12
- // In little-endian, first word should be: 97 + (97 << 8) + (97 << 16) + (97 << 24)
13
- const expectedFirstWord = 97 + (97 << 8) + (97 << 16) + (97 << 24);
14
- expect(result[0]).toBe(expectedFirstWord);
15
- });
16
-
17
- test('should handle empty string', () => {
18
- const result = md5blk('');
19
- expect(result).toHaveLength(16);
20
-
21
- // All words should be 0
22
- for (let i = 0; i < 16; i++) {
23
- expect(result[i]).toBe(0);
24
- }
25
- });
26
-
27
- test('should handle partial block', () => {
28
- // Test with less than 64 characters
29
- // Note: md5blk always processes 64 characters, padding with null bytes
30
- const input = 'hello world';
31
- const result = md5blk(input);
32
-
33
- expect(result).toHaveLength(16);
34
-
35
- // First word should contain 'h' (104), 'e' (101), 'l' (108), 'l' (108)
36
- const expectedFirstWord = 104 + (101 << 8) + (108 << 16) + (108 << 24);
37
- expect(result[0]).toBe(expectedFirstWord);
38
-
39
- // Second word should contain 'o' (111), ' ' (32), 'w' (119), 'o' (111)
40
- const expectedSecondWord = 111 + (32 << 8) + (119 << 16) + (111 << 24);
41
- expect(result[1]).toBe(expectedSecondWord);
42
-
43
- // Third word should contain 'r' (114), 'l' (108), 'd' (100), null (0)
44
- const expectedThirdWord = 114 + (108 << 8) + (100 << 16) + (0 << 24);
45
- expect(result[2]).toBe(expectedThirdWord);
46
- });
47
-
48
- test('should convert characters correctly', () => {
49
- const input = 'abcd';
50
- const result = md5blk(input);
51
-
52
- // 'a'(97), 'b'(98), 'c'(99), 'd'(100)
53
- const expectedWord = 97 + (98 << 8) + (99 << 16) + (100 << 24);
54
- expect(result[0]).toBe(expectedWord);
55
-
56
- // Remaining words should be 0
57
- for (let i = 1; i < 16; i++) {
58
- expect(result[i]).toBe(0);
59
- }
60
- });
61
- });
@@ -1,48 +0,0 @@
1
- import md5cycle from '../src/md5cycle';
2
-
3
- describe('md5cycle', () => {
4
- test('should update state correctly', () => {
5
- const state = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476];
6
- const block = new Array(16).fill(0);
7
-
8
- // Make a copy for comparison
9
- const originalState = [...state];
10
-
11
- md5cycle(state, block);
12
-
13
- // After processing, state should be different
14
- expect(state).not.toEqual(originalState);
15
-
16
- // All elements should be 32-bit integers
17
- state.forEach((val) => {
18
- expect(Number.isInteger(val)).toBe(true);
19
- expect(val).toBeGreaterThanOrEqual(-0x80000000);
20
- expect(val).toBeLessThanOrEqual(0xffffffff);
21
- });
22
- });
23
-
24
- test('should handle custom add32 functions', () => {
25
- const state = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476];
26
- const block = new Array(16).fill(0x12345678);
27
-
28
- const customAdd32 = jest.fn((x: number, y: number) => (x + y) & 0xffffffff);
29
-
30
- md5cycle(state, block, customAdd32);
31
-
32
- // Custom add32 function should have been called
33
- expect(customAdd32).toHaveBeenCalled();
34
- });
35
-
36
- test('should use default add32 when fn is undefined', () => {
37
- const state = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476];
38
- const block = new Array(16).fill(0);
39
-
40
- // Since we can't easily mock the default import in md5cycle,
41
- // we'll test the behavior by ensuring state changes
42
- const originalState = [...state];
43
-
44
- md5cycle(state, block);
45
-
46
- expect(state).not.toEqual(originalState);
47
- });
48
- });