Files
ytplayer/frontend/sha256.test.js

75 lines
3.2 KiB
JavaScript

'use strict';
const { test } = require('node:test');
const assert = require('node:assert');
const crypto = require('node:crypto');
const Sha256 = require('./sha256');
const ref = (buf) => crypto.createHash('sha256').update(buf).digest('hex');
test('known vectors', () => {
assert.strictEqual(Sha256.hex(new Uint8Array(0)), 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855');
assert.strictEqual(Sha256.hex(new TextEncoder().encode('abc')), 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad');
assert.strictEqual(
Sha256.hex(new TextEncoder().encode('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')),
'248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1');
});
test('every length around block boundaries matches node:crypto', () => {
for (let n = 0; n <= 200; n++) {
const buf = crypto.randomBytes(n);
assert.strictEqual(Sha256.hex(new Uint8Array(buf)), ref(buf), 'length ' + n);
}
});
test('random chunk boundaries give the same digest as one shot', () => {
const buf = crypto.randomBytes(3 * 1024 * 1024 + 17);
for (let round = 0; round < 5; round++) {
const h = Sha256.create();
let pos = 0;
while (pos < buf.length) {
const n = Math.min(buf.length - pos, 1 + Math.floor(Math.random() * 200000));
h.update(new Uint8Array(buf.buffer, buf.byteOffset + pos, n));
pos += n;
}
assert.strictEqual(h.hex(), ref(buf));
assert.strictEqual(h.bytes, buf.length);
}
});
test('update after digest throws; isHex', () => {
const h = Sha256.create();
h.hex();
assert.throws(() => h.update(new Uint8Array(1)));
assert.ok(Sha256.isHex(ref(Buffer.from('x'))));
assert.ok(!Sha256.isHex('ABC'));
});
// ---- WebAssembly engine ----
test('wasm engine is available in Node and matches the JS engine and node:crypto', () => {
const crypto = require('node:crypto');
assert.equal(Sha256.engine(), 'wasm');
const sizes = [0, 1, 55, 56, 63, 64, 65, 1000, (1 << 20) - 1, 1 << 20, (1 << 20) + 1, 3_000_001];
for (const n of sizes) {
const buf = Buffer.alloc(n).map((_, i) => (i * 7 + n) & 255);
const want = crypto.createHash('sha256').update(buf).digest('hex');
assert.equal(Sha256.create().update(buf).hex(), want, `wasm ${n}`);
assert.equal(Sha256.create({ js: true }).update(buf).hex(), want, `js ${n}`);
}
});
test('wasm engine hashes streamed odd-sized chunks like one-shot', () => {
const crypto = require('node:crypto');
const buf = Buffer.alloc(2_500_003).map((_, i) => (i * 13) & 255);
const h = Sha256.create();
for (let o = 0; o < buf.length; o += 77_777) h.update(buf.subarray(o, o + 77_777));
assert.equal(h.hex(), crypto.createHash('sha256').update(buf).digest('hex'));
});
test('falls back to the JS engine when WebAssembly is unavailable', () => {
const { execFileSync } = require('node:child_process');
const out = execFileSync(process.execPath, ['-e',
"delete globalThis.WebAssembly; const S=require('./frontend/sha256.js');" +
"console.log(S.engine(), S.hex(new TextEncoder().encode('abc')))"], { cwd: require('node:path').join(__dirname, '..') }).toString().trim();
assert.equal(out, 'js ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad');
});