mirror of
https://github.com/webinstall/webi-installers.git
synced 2026-04-06 10:26:49 +00:00
test: add installer resolution test for serve-installer.js path
Exercises the helper() function that `curl webi.sh/bat` actually hits. 9 passing, 6 known issues documented: - WATERFALL libc->gnu gap (build-classifier submodule) - ANYOS/ANYARCH .git source URLs matched before platform binaries
This commit is contained in:
@@ -46,6 +46,18 @@ The Go cache filters releases more aggressively than the old Node normalize.js:
|
||||
- These are improvements — the filtered results better reflect what webi can
|
||||
actually install.
|
||||
|
||||
### Known Issues Needing Resolution
|
||||
|
||||
- **WATERFALL libc vs gnu**: The Go cache correctly uses `libc='gnu'` for
|
||||
glibc-linked Linux binaries (Rust projects like bat, rg; also node). The
|
||||
build-classifier WATERFALL maps `libc` => `['none', 'libc']` but never tries
|
||||
`gnu`, so Linux glibc hosts can't match these packages. Fix needed in
|
||||
`host-targets.js`: `libc: ['none', 'gnu', 'libc']`. See QUESTIONS.md in the
|
||||
Go agent worktree.
|
||||
- **ANYOS/ANYARCH .git priority**: Packages like caddy and jq have `.git`
|
||||
source URLs classified as `ANYOS`/`ANYARCH`. The triplet enumeration tries
|
||||
ANYOS before specific OS, so `.git` matches before platform-specific binaries.
|
||||
|
||||
### Known Pre-existing Issues
|
||||
|
||||
- **`transform-releases.js` self-test**: The `if (require.main === module)`
|
||||
|
||||
232
_webi/test-installer-resolve.js
Normal file
232
_webi/test-installer-resolve.js
Normal file
@@ -0,0 +1,232 @@
|
||||
'use strict';
|
||||
|
||||
let InstallerServer = require('./serve-installer.js');
|
||||
let Builds = require('./builds.js');
|
||||
|
||||
// Real User-Agent strings sent by webi bootstrap scripts.
|
||||
//
|
||||
// Known issues (not regressions from cache-only migration):
|
||||
//
|
||||
// 1. WATERFALL libc vs gnu: The WATERFALL maps `libc` => ['none', 'libc']
|
||||
// but packages with explicit gnu in filenames (Rust projects) get classified
|
||||
// as libc='gnu'. A glibc host sending `libc` in the UA won't match `gnu`
|
||||
// triplets. Needs a build-classifier submodule update.
|
||||
//
|
||||
// 2. ANYOS/ANYARCH priority: The triplet enumeration tries ANYOS/ANYARCH
|
||||
// before specific OS/arch. Packages whose Go cache includes source repo
|
||||
// URLs (`.git`) as releases get matched to ANYOS before platform-specific
|
||||
// binaries. The Go cache or selectPackage needs to handle this.
|
||||
|
||||
let UA_CASES = [
|
||||
// === macOS (no libc issue — darwin uses libc='none') ===
|
||||
{
|
||||
label: 'bat macOS arm64',
|
||||
pkg: 'bat',
|
||||
ua: 'aarch64/unknown Darwin/24.2.0 libc',
|
||||
expectOs: 'darwin',
|
||||
expectArch: 'aarch64',
|
||||
expectExt: 'tar.gz',
|
||||
},
|
||||
{
|
||||
label: 'bat macOS amd64',
|
||||
pkg: 'bat',
|
||||
ua: 'x86_64/unknown Darwin/23.0.0 libc',
|
||||
expectOs: 'darwin',
|
||||
expectArch: 'x86_64',
|
||||
expectExt: 'tar.gz',
|
||||
},
|
||||
{
|
||||
label: 'go macOS arm64',
|
||||
pkg: 'go',
|
||||
ua: 'aarch64/unknown Darwin/24.2.0 libc',
|
||||
expectOs: 'darwin',
|
||||
expectArch: 'aarch64',
|
||||
expectExt: 'tar.gz',
|
||||
},
|
||||
{
|
||||
label: 'node macOS arm64',
|
||||
pkg: 'node',
|
||||
ua: 'aarch64/unknown Darwin/24.2.0 libc',
|
||||
expectOs: 'darwin',
|
||||
expectArch: 'aarch64',
|
||||
expectExt: 'tar.gz',
|
||||
},
|
||||
{
|
||||
label: 'rg macOS arm64',
|
||||
pkg: 'rg',
|
||||
ua: 'aarch64/unknown Darwin/24.2.0 libc',
|
||||
expectOs: 'darwin',
|
||||
expectArch: 'aarch64',
|
||||
expectExt: 'tar.gz',
|
||||
},
|
||||
|
||||
// === Windows ===
|
||||
{
|
||||
label: 'bat Windows amd64',
|
||||
pkg: 'bat',
|
||||
ua: 'x86_64/unknown Windows/10.0.19041 msvc',
|
||||
expectOs: 'windows',
|
||||
expectArch: 'x86_64',
|
||||
expectExt: 'zip',
|
||||
},
|
||||
{
|
||||
label: 'go Windows amd64',
|
||||
pkg: 'go',
|
||||
ua: 'x86_64/unknown Windows/10.0.19041 msvc',
|
||||
expectOs: 'windows',
|
||||
expectArch: 'x86_64',
|
||||
expectExt: 'zip',
|
||||
},
|
||||
|
||||
// === Linux musl (Alpine/Docker) ===
|
||||
{
|
||||
label: 'bat Linux musl',
|
||||
pkg: 'bat',
|
||||
ua: 'x86_64/unknown Linux/5.15.0 musl',
|
||||
expectOs: 'linux',
|
||||
expectArch: 'x86_64',
|
||||
expectExt: 'tar.gz',
|
||||
},
|
||||
|
||||
// === Linux glibc — packages with libc='none' in cache ===
|
||||
{
|
||||
label: 'go Linux amd64',
|
||||
pkg: 'go',
|
||||
ua: 'x86_64/unknown Linux/5.15.0 libc',
|
||||
expectOs: 'linux',
|
||||
expectArch: 'x86_64',
|
||||
expectExt: 'tar.gz',
|
||||
},
|
||||
// === Known: WATERFALL libc vs gnu ===
|
||||
// Packages whose Go cache has libc='gnu' for Linux glibc builds.
|
||||
// The WATERFALL maps `libc` => ['none', 'libc'] but never tries 'gnu'.
|
||||
{
|
||||
label: 'bat Linux amd64 (known: WATERFALL libc vs gnu)',
|
||||
pkg: 'bat',
|
||||
ua: 'x86_64/unknown Linux/5.15.0 libc',
|
||||
known: 'WATERFALL libc->gnu gap',
|
||||
},
|
||||
{
|
||||
label: 'rg Linux amd64 (known: WATERFALL libc vs gnu)',
|
||||
pkg: 'rg',
|
||||
ua: 'x86_64/unknown Linux/5.15.0 libc',
|
||||
known: 'WATERFALL libc->gnu gap',
|
||||
},
|
||||
{
|
||||
label: 'node Linux amd64 (known: WATERFALL libc vs gnu)',
|
||||
pkg: 'node',
|
||||
ua: 'x86_64/unknown Linux/5.15.0 libc',
|
||||
known: 'WATERFALL libc->gnu gap',
|
||||
},
|
||||
|
||||
// === Known: ANYOS/ANYARCH .git priority ===
|
||||
{
|
||||
label: 'jq macOS arm64 (known: ANYOS .git priority)',
|
||||
pkg: 'jq',
|
||||
ua: 'aarch64/unknown Darwin/24.2.0 libc',
|
||||
known: 'ANYOS .git matched before platform binary',
|
||||
},
|
||||
{
|
||||
label: 'caddy macOS arm64 (known: ANYOS .git priority)',
|
||||
pkg: 'caddy',
|
||||
ua: 'aarch64/unknown Darwin/24.2.0 libc',
|
||||
known: 'ANYOS .git matched before platform binary',
|
||||
},
|
||||
{
|
||||
label: 'caddy Linux amd64 (known: ANYOS .git priority)',
|
||||
pkg: 'caddy',
|
||||
ua: 'x86_64/unknown Linux/5.15.0 libc',
|
||||
known: 'ANYOS .git matched before platform binary',
|
||||
},
|
||||
];
|
||||
|
||||
async function main() {
|
||||
let failures = 0;
|
||||
let passes = 0;
|
||||
let knowns = 0;
|
||||
let errors = 0;
|
||||
|
||||
console.log('Initializing build cache...');
|
||||
await Builds.init();
|
||||
console.log('');
|
||||
|
||||
console.log('=== Installer Resolution Tests ===');
|
||||
console.log('');
|
||||
|
||||
for (let tc of UA_CASES) {
|
||||
try {
|
||||
let [pkg, params] = await InstallerServer.helper({
|
||||
unameAgent: tc.ua,
|
||||
projectName: tc.pkg,
|
||||
tag: 'stable',
|
||||
formats: [],
|
||||
libc: '',
|
||||
});
|
||||
|
||||
// Known issue — just verify it fails as expected
|
||||
if (tc.known) {
|
||||
if (pkg.channel === 'error' || !pkg.download || pkg.download.includes('doesntexist') || pkg.ext === 'git') {
|
||||
console.log(` KNOWN ${tc.label}`);
|
||||
knowns++;
|
||||
} else {
|
||||
console.log(` PASS ${tc.label} (known issue resolved!): v${pkg.version} .${pkg.ext}`);
|
||||
passes++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pkg.channel === 'error') {
|
||||
console.log(` FAIL ${tc.label}: resolved to error package`);
|
||||
failures++;
|
||||
continue;
|
||||
}
|
||||
|
||||
let diffs = [];
|
||||
|
||||
if (tc.expectOs && pkg.os !== tc.expectOs) {
|
||||
diffs.push(`os: got=${pkg.os} want=${tc.expectOs}`);
|
||||
}
|
||||
if (tc.expectArch && pkg.arch !== tc.expectArch) {
|
||||
diffs.push(`arch: got=${pkg.arch} want=${tc.expectArch}`);
|
||||
}
|
||||
if (tc.expectExt && pkg.ext !== tc.expectExt) {
|
||||
diffs.push(`ext: got=${pkg.ext} want=${tc.expectExt}`);
|
||||
}
|
||||
|
||||
if (!pkg.version || pkg.version === '0.0.0') {
|
||||
diffs.push('version: missing or zero');
|
||||
}
|
||||
|
||||
if (!pkg.download || pkg.download.includes('doesntexist')) {
|
||||
diffs.push('download: missing or error');
|
||||
}
|
||||
|
||||
if (diffs.length > 0) {
|
||||
console.log(` FAIL ${tc.label}: ${diffs.join(', ')}`);
|
||||
failures++;
|
||||
} else {
|
||||
console.log(` PASS ${tc.label}: v${pkg.version} .${pkg.ext} ${pkg.download.split('/').pop()}`);
|
||||
passes++;
|
||||
}
|
||||
} catch (err) {
|
||||
if (tc.known) {
|
||||
console.log(` KNOWN ${tc.label} (error: ${err.message})`);
|
||||
knowns++;
|
||||
continue;
|
||||
}
|
||||
console.log(` ERROR ${tc.label}: ${err.message}`);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log('');
|
||||
console.log(`=== Results: ${passes} passed, ${failures} failed, ${knowns} known, ${errors} errors ===`);
|
||||
if (failures > 0 || errors > 0) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(function (err) {
|
||||
console.error(err.stack);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user