mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-09-11 05:16:27 -07:00
154 lines
5.2 KiB
TypeScript
154 lines
5.2 KiB
TypeScript
import { describe, expect, test } from 'bun:test';
|
|
import { createHash } from 'node:crypto';
|
|
import fs from 'node:fs/promises';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import {
|
|
downloadArchive,
|
|
parseRegisteredRepositories,
|
|
parseSourceManifest,
|
|
validateBunPins,
|
|
validateRuntimeAlignment,
|
|
} from './package-bun-source.mjs';
|
|
|
|
const projectRoot = path.resolve(import.meta.dir, '..');
|
|
|
|
describe('Bun corresponding-source manifest', () => {
|
|
test('removes partial downloads when placing a valid archive fails', async () => {
|
|
const cacheDir = await fs.mkdtemp(path.join(os.tmpdir(), 'subminer-bun-source-test-'));
|
|
try {
|
|
const payload = new Uint8Array([1, 2, 3]);
|
|
const source = {
|
|
name: 'fixture',
|
|
repository: 'example/fixture',
|
|
revision: 'a'.repeat(40),
|
|
sha256: createHash('sha256').update(payload).digest('hex'),
|
|
};
|
|
const archivePath = path.join(cacheDir, `${source.name}-${source.revision}.tar.gz`);
|
|
await expect(
|
|
downloadArchive(source, cacheDir, async () => {
|
|
await fs.mkdir(archivePath);
|
|
return { ok: true, status: 200, body: new Response(payload).body };
|
|
}),
|
|
).rejects.toMatchObject({ syscall: 'rename' });
|
|
|
|
const entries = await fs.readdir(cacheDir);
|
|
expect(entries.filter((entry) => entry.includes('.download-'))).toEqual([]);
|
|
} finally {
|
|
await fs.rm(cacheDir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('pins the source to the revision reported by the distributed binary', async () => {
|
|
const manifest = parseSourceManifest(
|
|
JSON.parse(
|
|
await fs.readFile(path.join(projectRoot, 'build/bun-source-manifest.json'), 'utf8'),
|
|
),
|
|
);
|
|
|
|
expect(manifest.version).toBe('1.3.5');
|
|
expect(manifest.bunRevision).toBe('1e86cebd74a5723e818b5c0555276b646bcf0e4c');
|
|
expect(manifest.releaseTagCommit).toBe('fa5a5bbe556a4bda5bde77b4013aa6c3bb4ec9ab');
|
|
expect(manifest.sources.find((source) => source.name === 'WebKit')?.revision).toBe(
|
|
'6d0f3aac0b817cc01a846b3754b21271adedac12',
|
|
);
|
|
expect(manifest.sources.find((source) => source.name === 'tinycc')?.revision).toBe(
|
|
'29985a3b59898861442fa3b43f663fc1af2591d7',
|
|
);
|
|
});
|
|
|
|
test('parses commit and tag registrations from Bun CMake', () => {
|
|
const registrations = parseRegisteredRepositories(`
|
|
register_repository(
|
|
NAME tinycc
|
|
REPOSITORY oven-sh/tinycc
|
|
COMMIT
|
|
# A comment between the field and its value is valid CMake.
|
|
29985a3b59898861442fa3b43f663fc1af2591d7
|
|
)
|
|
register_repository(
|
|
NAME brotli
|
|
REPOSITORY google/brotli
|
|
TAG v1.1.0
|
|
)
|
|
`);
|
|
|
|
expect(registrations.get('tinycc')).toEqual({
|
|
repository: 'oven-sh/tinycc',
|
|
kind: 'commit',
|
|
reference: '29985a3b59898861442fa3b43f663fc1af2591d7',
|
|
});
|
|
expect(registrations.get('brotli')).toEqual({
|
|
repository: 'google/brotli',
|
|
kind: 'tag',
|
|
reference: 'v1.1.0',
|
|
});
|
|
});
|
|
|
|
test('rejects stale runtime or package-manager pins', async () => {
|
|
const manifest = parseSourceManifest(
|
|
JSON.parse(
|
|
await fs.readFile(path.join(projectRoot, 'build/bun-source-manifest.json'), 'utf8'),
|
|
),
|
|
);
|
|
const runtimeManifest = {
|
|
version: manifest.version,
|
|
bunRevision: manifest.bunRevision,
|
|
correspondingSourceAsset: manifest.archiveName,
|
|
};
|
|
|
|
expect(() =>
|
|
validateRuntimeAlignment(manifest, { packageManager: 'bun@1.3.5' }, runtimeManifest),
|
|
).not.toThrow();
|
|
expect(() =>
|
|
validateRuntimeAlignment(manifest, { packageManager: 'bun@1.3.6' }, runtimeManifest),
|
|
).toThrow('package.json must pin bun@1.3.5');
|
|
expect(() =>
|
|
validateRuntimeAlignment(
|
|
manifest,
|
|
{ packageManager: 'bun@1.3.5' },
|
|
{
|
|
...runtimeManifest,
|
|
correspondingSourceAsset: 'stale.tar.gz',
|
|
},
|
|
),
|
|
).toThrow('correspondingSourceAsset does not match');
|
|
});
|
|
|
|
test('rejects drift in CMake dependency and WebKit pins', async () => {
|
|
const manifest = parseSourceManifest(
|
|
JSON.parse(
|
|
await fs.readFile(path.join(projectRoot, 'build/bun-source-manifest.json'), 'utf8'),
|
|
),
|
|
);
|
|
const registrations = manifest.sources
|
|
.filter((source) => source.destination.startsWith('bun/vendor/') && source.name !== 'WebKit')
|
|
.map(
|
|
(source) => `register_repository(
|
|
NAME ${source.name}
|
|
REPOSITORY ${source.repository}
|
|
${source.upstreamReference ? 'TAG' : 'COMMIT'} ${source.upstreamReference ?? source.revision}
|
|
)`,
|
|
)
|
|
.join('\n');
|
|
|
|
expect(() =>
|
|
validateBunPins(
|
|
manifest,
|
|
[registrations],
|
|
'set(WEBKIT_VERSION 6d0f3aac0b817cc01a846b3754b21271adedac12)',
|
|
),
|
|
).not.toThrow();
|
|
expect(() =>
|
|
validateBunPins(
|
|
manifest,
|
|
[registrations.replace('29985a3b59898861442fa3b43f663fc1af2591d7', '0'.repeat(40))],
|
|
'set(WEBKIT_VERSION 6d0f3aac0b817cc01a846b3754b21271adedac12)',
|
|
),
|
|
).toThrow('revision mismatch for tinycc');
|
|
expect(() =>
|
|
validateBunPins(manifest, [registrations], `set(WEBKIT_VERSION ${'0'.repeat(40)})`),
|
|
).toThrow('WebKit revision does not match');
|
|
});
|
|
});
|