You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
83 lines
2.7 KiB
83 lines
2.7 KiB
// Test helpers: access to the vendored testdata/ of the Go reference. Tests
|
|
// only; never part of the library.
|
|
|
|
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { expect } from 'vitest';
|
|
import { errorCode } from '../errors.ts';
|
|
|
|
/** Absolute path of the repository's testdata/. */
|
|
export const TESTDATA = fileURLToPath(new URL('../../../../testdata/', import.meta.url));
|
|
|
|
export function testdataPath(rel: string): string {
|
|
return join(TESTDATA, rel);
|
|
}
|
|
|
|
export function hasTestdata(rel: string): boolean {
|
|
return existsSync(testdataPath(rel));
|
|
}
|
|
|
|
export function readBytes(rel: string): Uint8Array {
|
|
return new Uint8Array(readFileSync(testdataPath(rel)));
|
|
}
|
|
|
|
export function readJSON<T = unknown>(rel: string): T {
|
|
return JSON.parse(readFileSync(testdataPath(rel), 'utf8')) as T;
|
|
}
|
|
|
|
/** Files under testdata/<dir> (recursively) whose name ends with `suffix`, relative to testdata/. */
|
|
export function listTestdata(dir: string, suffix: string): string[] {
|
|
const root = testdataPath(dir);
|
|
if (!existsSync(root)) return [];
|
|
const out: string[] = [];
|
|
const walk = (rel: string): void => {
|
|
for (const e of readdirSync(join(root, rel), { withFileTypes: true })) {
|
|
const r = rel === '' ? e.name : `${rel}/${e.name}`;
|
|
if (e.isDirectory()) walk(r);
|
|
else if (e.name.endsWith(suffix)) out.push(dir === '' ? r : `${dir}/${r}`);
|
|
}
|
|
};
|
|
walk('');
|
|
return out.sort();
|
|
}
|
|
|
|
/** Bytes from hexadecimal, ignoring spaces. */
|
|
export function h(s: string): Uint8Array {
|
|
return new Uint8Array(Buffer.from(s.replace(/\s+/g, ''), 'hex'));
|
|
}
|
|
|
|
export function hx(b: Uint8Array): string {
|
|
return Buffer.from(b).toString('hex');
|
|
}
|
|
|
|
/**
|
|
* Asserts that `fn` throws a DateKeysError with `code` (and a message matching
|
|
* `msg`); `label` names the case in a failure.
|
|
*/
|
|
export function expectCode(fn: () => unknown, code: string, msg?: RegExp, label?: string): void {
|
|
let caught: unknown;
|
|
try {
|
|
fn();
|
|
} catch (err) {
|
|
caught = err;
|
|
}
|
|
const where = label === undefined ? '' : `${label}: `;
|
|
expect(caught, `${where}expected a thrown error`).toBeDefined();
|
|
expect(errorCode(caught), `${where}${(caught as Error).message}`).toBe(code);
|
|
if (msg) expect((caught as Error).message, label).toMatch(msg);
|
|
}
|
|
|
|
/** Async variant of expectCode. */
|
|
export async function expectCodeAsync(fn: () => Promise<unknown>, code: string, msg?: RegExp): Promise<void> {
|
|
let caught: unknown;
|
|
try {
|
|
await fn();
|
|
} catch (err) {
|
|
caught = err;
|
|
}
|
|
expect(caught, 'expected a rejected promise').toBeDefined();
|
|
expect(errorCode(caught), (caught as Error).message).toBe(code);
|
|
if (msg) expect((caught as Error).message).toMatch(msg);
|
|
}
|