mirror of https://github.com/webpack/webpack.git
				
				
				
			
		
			
				
	
	
		
			170 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| "use strict";
 | |
| 
 | |
| const { createHash, randomBytes } = require("crypto");
 | |
| 
 | |
| const wasmHashes = {
 | |
| 	xxhash64: () => {
 | |
| 		const createHash = require("../lib/util/hash/xxhash64");
 | |
| 		const createReferenceHash =
 | |
| 			require("hash-wasm/dist/xxhash64.umd.min").createXXHash64;
 | |
| 
 | |
| 		return {
 | |
| 			createHash,
 | |
| 			createReferenceHash: async () => (await createReferenceHash()).init(),
 | |
| 			regExp: /^[0-9a-f]{16}$/
 | |
| 		};
 | |
| 	},
 | |
| 	"xxhash64-createHash": () => {
 | |
| 		const createXxHash = require("../lib/util/hash/xxhash64");
 | |
| 		const createHash = require("../lib/util/createHash");
 | |
| 
 | |
| 		return {
 | |
| 			createHash: () => createHash("xxhash64"),
 | |
| 			createReferenceHash: createXxHash,
 | |
| 			regExp: /^[0-9a-f]{16}$/
 | |
| 		};
 | |
| 	},
 | |
| 	md4: () => {
 | |
| 		const createMd4Hash = require("../lib/util/hash/md4");
 | |
| 
 | |
| 		return {
 | |
| 			createHash: createMd4Hash,
 | |
| 			createReferenceHash:
 | |
| 				Number.parseInt(process.version.slice(1), 10) < 17
 | |
| 					? async () => createHash("md4")
 | |
| 					: createMd4Hash,
 | |
| 			regExp: /^[0-9a-f]{32}$/
 | |
| 		};
 | |
| 	},
 | |
| 	"md4-createHash": () => {
 | |
| 		const createMd4Hash = require("../lib/util/hash/md4");
 | |
| 		const createHash = require("../lib/util/createHash");
 | |
| 
 | |
| 		return {
 | |
| 			createHash: () => createHash("md4"),
 | |
| 			createReferenceHash: createMd4Hash,
 | |
| 			regExp: /^[0-9a-f]{32}$/
 | |
| 		};
 | |
| 	}
 | |
| };
 | |
| 
 | |
| for (const name of Object.keys(wasmHashes)) {
 | |
| 	const { createHash, createReferenceHash, regExp } = wasmHashes[name]();
 | |
| 
 | |
| 	describe(name, () => {
 | |
| 		const sizes = [
 | |
| 			1,
 | |
| 			2,
 | |
| 			3,
 | |
| 			4,
 | |
| 			5,
 | |
| 			7,
 | |
| 			8,
 | |
| 			9,
 | |
| 			16,
 | |
| 			31,
 | |
| 			32,
 | |
| 			33,
 | |
| 			64 - 10,
 | |
| 			64 - 9,
 | |
| 			64 - 8,
 | |
| 			63,
 | |
| 			64,
 | |
| 			65,
 | |
| 			100,
 | |
| 			1000,
 | |
| 			65536 - 1,
 | |
| 			65536,
 | |
| 			65536 + 1,
 | |
| 			65536 + 31,
 | |
| 			65536 * 5,
 | |
| 			65536 * 7 - 1,
 | |
| 			65536 * 9 + 31
 | |
| 		];
 | |
| 
 | |
| 		const test = (name, sizes) => {
 | |
| 			it(`${name} should generate a hash from binary data`, async () => {
 | |
| 				const hash = createHash();
 | |
| 				const hashString = createHash();
 | |
| 				const reference = await createReferenceHash();
 | |
| 				for (const size of sizes) {
 | |
| 					const bytes = randomBytes(size);
 | |
| 					const string = bytes.toString("base64");
 | |
| 					hash.update(bytes);
 | |
| 					hashString.update(string, "base64");
 | |
| 					reference.update(bytes);
 | |
| 				}
 | |
| 				const result = hash.digest("hex");
 | |
| 				expect(result).toMatch(regExp);
 | |
| 				const resultFromString = hashString.digest("hex");
 | |
| 				expect(resultFromString).toMatch(regExp);
 | |
| 				const expected = reference.digest("hex");
 | |
| 				expect(result).toBe(expected);
 | |
| 				expect(resultFromString).toBe(expected);
 | |
| 			});
 | |
| 		};
 | |
| 
 | |
| 		test("empty hash", []);
 | |
| 
 | |
| 		for (const size of sizes) {
 | |
| 			test(`single update ${size} bytes`, [size]);
 | |
| 		}
 | |
| 
 | |
| 		for (const size1 of sizes) {
 | |
| 			for (const size2 of sizes) {
 | |
| 				test(`two updates ${size1} + ${size2} bytes`, [size1, size2]);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		test("many updates 1", sizes);
 | |
| 
 | |
| 		test("many updates 2", [...sizes].reverse());
 | |
| 
 | |
| 		test("many updates 3", [...sizes, ...[...sizes].reverse()]);
 | |
| 
 | |
| 		test("many updates 4", [...[...sizes].reverse(), ...sizes]);
 | |
| 
 | |
| 		const unicodeTest = (name, codePoints) => {
 | |
| 			it(`${name} should hash unicode chars correctly`, async () => {
 | |
| 				const hash = createHash();
 | |
| 				const reference = await createReferenceHash();
 | |
| 				const str =
 | |
| 					typeof codePoints === "string"
 | |
| 						? codePoints
 | |
| 						: String.fromCodePoint(...codePoints);
 | |
| 				hash.update(str);
 | |
| 				reference.update(str);
 | |
| 				const result = hash.digest("hex");
 | |
| 				expect(result).toMatch(regExp);
 | |
| 				const expected = reference.digest("hex");
 | |
| 				expect(result).toBe(expected);
 | |
| 			});
 | |
| 		};
 | |
| 
 | |
| 		const unicodeRangeTest = (name, start, end) => {
 | |
| 			const codePoints = [];
 | |
| 			for (let i = start; i <= end; i++) {
 | |
| 				codePoints.push(i);
 | |
| 			}
 | |
| 			unicodeTest(name, codePoints);
 | |
| 		};
 | |
| 
 | |
| 		// cspell:word Thaana
 | |
| 		unicodeRangeTest("Latin-1 Supplement", 0xa0, 0xff);
 | |
| 		unicodeRangeTest("Latin Extended", 0x100, 0x24f);
 | |
| 		unicodeRangeTest("Thaana", 0x780, 0x7bf);
 | |
| 		unicodeRangeTest("Devanagari", 0x900, 0x97f);
 | |
| 		unicodeRangeTest("Emoticons", 0x1f600, 0x1f64f);
 | |
| 
 | |
| 		unicodeTest("with zero char", "abc\0💩");
 | |
| 		unicodeTest("weird code point after long code point", [1497, 243248]);
 | |
| 
 | |
| 		for (let i = 0; i < 1000; i++) {
 | |
| 			const chars = Array.from({ length: 20 }, () =>
 | |
| 				Math.floor(Math.random() * 0x10ffff)
 | |
| 			);
 | |
| 			unicodeTest(`fuzzy ${JSON.stringify(chars)}`, chars);
 | |
| 		}
 | |
| 	});
 | |
| }
 |