streaming RAR extractor
jsr.io/@mary/rar
jsr
1import { crc32 } from '@mary/crc32';
2
3import { decodeOldLzss15, decodeOldLzss20 } from '../lib/rar3/oldlzss.ts';
4
5/**
6 * @module
7 *
8 * regression tests for the RAR1.5/2.x LZSS decoders. each test pins a
9 * compressed byte stream and the expected decompressed payload, sourced
10 * from the vendored rarfile corpus. inputs validated against system unrar
11 * via rarfile's `rar3_decompress` shell-out.
12 */
13
14const expectText = (
15 out: Uint8Array | undefined,
16 expected: string,
17 expectedCrc: number,
18 label: string,
19): void => {
20 if (out === undefined) {
21 throw new Error(`${label}: decoder returned undefined`);
22 }
23 const actual = new TextDecoder().decode(out);
24 if (actual !== expected) {
25 throw new Error(
26 `${label}: text mismatch, expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`,
27 );
28 }
29 const crc = crc32(out) & 0xffff;
30 if (crc !== expectedCrc) {
31 throw new Error(
32 `${label}: crc mismatch, expected 0x${expectedCrc.toString(16)}, got 0x${crc.toString(16)}`,
33 );
34 }
35};
36
37Deno.test('decodeOldLzss15: rarcomment fixture (16-byte archive comment)', () => {
38 // the v15 oldComment subblock data area from rar15-comment.rar's MAIN
39 // header: declen=16, expected text 'RARcomment -----', dataCrc=0xd0f2.
40 const data = Uint8Array.fromHex('0f92e507a3f5feb48f4a0f5ded15e1344000');
41 expectText(decodeOldLzss15(data, 16), 'RARcomment -----', 0xd0f2, 'v15 corpus');
42});
43
44Deno.test('decodeOldLzss15: empty input returns empty output', () => {
45 const out = decodeOldLzss15(new Uint8Array(0), 0);
46 if (out === undefined || out.length !== 0) {
47 throw new Error(`expected empty Uint8Array, got ${out}`);
48 }
49});
50
51Deno.test('decodeOldLzss20: rarcomment fixture (10-byte archive comment)', () => {
52 // the v20 oldComment subblock data area from rar202-comment-nopsw.rar's
53 // MAIN header: declen=10, expected text 'RARcomment', dataCrc=0x50ee.
54 const data = Uint8Array.fromHex('10004c0000000000010a6da0a82b9f0795fe07aba381ada980');
55 expectText(decodeOldLzss20(data, 10), 'RARcomment', 0x50ee, 'v20 corpus');
56});
57
58Deno.test('decodeOldLzss20: empty input returns empty output', () => {
59 const out = decodeOldLzss20(new Uint8Array(0), 0);
60 if (out === undefined || out.length !== 0) {
61 throw new Error(`expected empty Uint8Array, got ${out}`);
62 }
63});