mirror of
https://github.com/webinstall/webi-installers.git
synced 2026-04-06 10:26:49 +00:00
Compares local cache-only output against golden data fetched from the live API. Tests OS/arch/ext vocabulary, version format, and filtered query results for bat, go, node, rg, jq, caddy.
209 lines
6.9 KiB
JavaScript
209 lines
6.9 KiB
JavaScript
'use strict';
|
|
|
|
let Fs = require('node:fs/promises');
|
|
let Path = require('node:path');
|
|
|
|
let Releases = require('./transform-releases.js');
|
|
|
|
let TESTDATA_DIR = Path.join(__dirname, 'testdata');
|
|
|
|
// These mirror what the live API returns for /api/releases/{pkg}@stable.json?...
|
|
let FILTERED_CASES = [
|
|
{ pkg: 'bat', os: 'macos', arch: 'amd64' },
|
|
{ pkg: 'bat', os: 'macos', arch: 'arm64' },
|
|
{ pkg: 'bat', os: 'linux', arch: 'amd64' },
|
|
{ pkg: 'bat', os: 'windows', arch: 'amd64' },
|
|
{ pkg: 'go', os: 'macos', arch: 'amd64' },
|
|
{ pkg: 'go', os: 'macos', arch: 'arm64' },
|
|
{ pkg: 'go', os: 'linux', arch: 'amd64' },
|
|
{ pkg: 'go', os: 'windows', arch: 'amd64' },
|
|
{ pkg: 'rg', os: 'macos', arch: 'amd64' },
|
|
{ pkg: 'rg', os: 'macos', arch: 'arm64' },
|
|
{ pkg: 'rg', os: 'linux', arch: 'amd64' },
|
|
{ pkg: 'rg', os: 'windows', arch: 'amd64' },
|
|
{ pkg: 'caddy', os: 'macos', arch: 'amd64' },
|
|
{ pkg: 'caddy', os: 'macos', arch: 'arm64' },
|
|
{ pkg: 'caddy', os: 'linux', arch: 'amd64' },
|
|
{ pkg: 'caddy', os: 'windows', arch: 'amd64' },
|
|
];
|
|
|
|
// Fields to compare between live and local
|
|
let COMPARE_FIELDS = ['version', 'os', 'arch', 'ext', 'libc', 'channel', 'download'];
|
|
|
|
async function main() {
|
|
let failures = 0;
|
|
let passes = 0;
|
|
let skips = 0;
|
|
|
|
// Test 1: Unfiltered release list — compare structure and field values
|
|
console.log('=== Test 1: Unfiltered /api/releases/{pkg}.json ===');
|
|
console.log('');
|
|
for (let pkg of ['bat', 'go', 'node', 'rg', 'jq', 'caddy']) {
|
|
let liveFile = `${TESTDATA_DIR}/live_${pkg}.json`;
|
|
let liveExists = await Fs.access(liveFile).then(
|
|
function () { return true; },
|
|
function () { return false; },
|
|
);
|
|
if (!liveExists) {
|
|
console.log(` SKIP ${pkg}: no golden data`);
|
|
skips++;
|
|
continue;
|
|
}
|
|
|
|
let liveJson = await Fs.readFile(liveFile, 'utf8');
|
|
let liveReleases = JSON.parse(liveJson);
|
|
|
|
let localResult = await Releases.getReleases({
|
|
pkg: pkg,
|
|
ver: '',
|
|
os: '',
|
|
arch: '',
|
|
libc: '',
|
|
lts: false,
|
|
channel: '',
|
|
formats: [],
|
|
limit: 100,
|
|
});
|
|
|
|
let localReleases = localResult.releases;
|
|
|
|
// Compare OS vocabulary
|
|
let liveOses = [...new Set(liveReleases.map(function (r) { return r.os; }))].sort();
|
|
let localOses = [...new Set(localReleases.map(function (r) { return r.os; }))].sort();
|
|
let osMatch = JSON.stringify(liveOses) === JSON.stringify(localOses);
|
|
if (!osMatch) {
|
|
console.log(` FAIL ${pkg} OS values: live=${JSON.stringify(liveOses)} local=${JSON.stringify(localOses)}`);
|
|
failures++;
|
|
} else {
|
|
console.log(` PASS ${pkg} OS values: ${JSON.stringify(liveOses)}`);
|
|
passes++;
|
|
}
|
|
|
|
// Compare arch vocabulary
|
|
let liveArches = [...new Set(liveReleases.map(function (r) { return r.arch; }))].sort();
|
|
let localArches = [...new Set(localReleases.map(function (r) { return r.arch; }))].sort();
|
|
let archMatch = JSON.stringify(liveArches) === JSON.stringify(localArches);
|
|
if (!archMatch) {
|
|
console.log(` FAIL ${pkg} arch values: live=${JSON.stringify(liveArches)} local=${JSON.stringify(localArches)}`);
|
|
failures++;
|
|
} else {
|
|
console.log(` PASS ${pkg} arch values: ${JSON.stringify(liveArches)}`);
|
|
passes++;
|
|
}
|
|
|
|
// Compare latest version
|
|
let liveLatest = liveReleases[0]?.version;
|
|
let localLatest = localReleases[0]?.version;
|
|
if (liveLatest !== localLatest) {
|
|
// Version differences may be expected if cache is newer/older
|
|
console.log(` WARN ${pkg} latest version: live=${liveLatest} local=${localLatest}`);
|
|
} else {
|
|
console.log(` PASS ${pkg} latest version: ${liveLatest}`);
|
|
passes++;
|
|
}
|
|
|
|
// Compare ext vocabulary
|
|
let liveExts = [...new Set(liveReleases.map(function (r) { return r.ext; }))].sort();
|
|
let localExts = [...new Set(localReleases.map(function (r) { return r.ext; }))].sort();
|
|
let extMatch = JSON.stringify(liveExts) === JSON.stringify(localExts);
|
|
if (!extMatch) {
|
|
console.log(` FAIL ${pkg} ext values: live=${JSON.stringify(liveExts)} local=${JSON.stringify(localExts)}`);
|
|
failures++;
|
|
} else {
|
|
console.log(` PASS ${pkg} ext values: ${JSON.stringify(liveExts)}`);
|
|
passes++;
|
|
}
|
|
|
|
// Compare that version strings don't have 'v' prefix
|
|
let localHasVPrefix = localReleases.some(function (r) {
|
|
return r.version.startsWith('v');
|
|
});
|
|
if (localHasVPrefix) {
|
|
console.log(` FAIL ${pkg} versions have 'v' prefix (should be stripped)`);
|
|
failures++;
|
|
} else {
|
|
console.log(` PASS ${pkg} no 'v' prefix on versions`);
|
|
passes++;
|
|
}
|
|
}
|
|
|
|
// Test 2: Filtered queries — compare selected package for specific OS/arch
|
|
console.log('');
|
|
console.log('=== Test 2: Filtered /api/releases/{pkg}@stable.json?os=...&arch=... ===');
|
|
console.log('');
|
|
for (let tc of FILTERED_CASES) {
|
|
let fname = `live_${tc.pkg}_os_${tc.os}_arch_${tc.arch}.json`;
|
|
let liveFile = `${TESTDATA_DIR}/${fname}`;
|
|
let liveExists = await Fs.access(liveFile).then(
|
|
function () { return true; },
|
|
function () { return false; },
|
|
);
|
|
if (!liveExists) {
|
|
skips++;
|
|
continue;
|
|
}
|
|
|
|
let liveJson = await Fs.readFile(liveFile, 'utf8');
|
|
let liveReleases = JSON.parse(liveJson);
|
|
let liveFirst = liveReleases[0];
|
|
if (!liveFirst || liveFirst.channel === 'error') {
|
|
console.log(` SKIP ${tc.pkg} ${tc.os}/${tc.arch}: live returned error/empty`);
|
|
skips++;
|
|
continue;
|
|
}
|
|
|
|
let localResult = await Releases.getReleases({
|
|
pkg: tc.pkg,
|
|
ver: '',
|
|
os: tc.os,
|
|
arch: tc.arch,
|
|
libc: '',
|
|
lts: false,
|
|
channel: 'stable',
|
|
formats: ['tar', 'zip', 'exe', 'xz'],
|
|
limit: 1,
|
|
});
|
|
let localFirst = localResult.releases[0];
|
|
|
|
if (!localFirst || localFirst.channel === 'error') {
|
|
console.log(` FAIL ${tc.pkg} ${tc.os}/${tc.arch}: local returned error/empty, live had ${liveFirst.version}`);
|
|
failures++;
|
|
continue;
|
|
}
|
|
|
|
let diffs = [];
|
|
for (let field of COMPARE_FIELDS) {
|
|
let liveVal = String(liveFirst[field] || '');
|
|
let localVal = String(localFirst[field] || '');
|
|
if (liveVal !== localVal) {
|
|
// Version differences are OK if cache age differs
|
|
if (field === 'version' || field === 'download' || field === 'date') {
|
|
continue;
|
|
}
|
|
diffs.push(`${field}: live=${liveVal} local=${localVal}`);
|
|
}
|
|
}
|
|
|
|
if (diffs.length > 0) {
|
|
console.log(` FAIL ${tc.pkg} ${tc.os}/${tc.arch}: ${diffs.join(', ')}`);
|
|
failures++;
|
|
} else {
|
|
let ver = localFirst.version;
|
|
let ext = localFirst.ext;
|
|
console.log(` PASS ${tc.pkg} ${tc.os}/${tc.arch}: v${ver} .${ext}`);
|
|
passes++;
|
|
}
|
|
}
|
|
|
|
console.log('');
|
|
console.log(`=== Results: ${passes} passed, ${failures} failed, ${skips} skipped ===`);
|
|
if (failures > 0) {
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
main().catch(function (err) {
|
|
console.error(err.stack);
|
|
process.exit(1);
|
|
});
|