55 lines
3.5 KiB
JavaScript
55 lines
3.5 KiB
JavaScript
// Verifies real-status-to-badge mapping without guessing a configured Auto result.
|
|
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import vm from 'node:vm';
|
|
|
|
const source = fs.readFileSync('src/admin/web/vhosts/render.js', 'utf8');
|
|
const block = source.slice(source.indexOf('const VHOST_PROTOCOL_FRESH_MS = '), source.indexOf('function render() {'));
|
|
assert(block.includes('function renderUpstreamProtocolBadges(status)'));
|
|
const rustClient = fs.readFileSync('src/upstream/client.rs', 'utf8');
|
|
const rustPool = fs.readFileSync('src/balance/pool_view.rs', 'utf8');
|
|
assert(rustClient.includes('self.inner.observe_protocol(value.version())'));
|
|
assert(rustClient.includes('let response = client.request(request).await;'));
|
|
for (const name of ['upstream_protocol_observed','upstream_protocol_last_seen_ms','upstream_protocol_http1_total','upstream_protocol_http2_total']) {
|
|
assert(rustPool.includes(`"${name}"`), name);
|
|
}
|
|
const en = JSON.parse(fs.readFileSync('langs/en_US.json', 'utf8')).translations;
|
|
const pl = JSON.parse(fs.readFileSync('langs/pl_pl.json', 'utf8')).translations;
|
|
for(const key of ['vhBackendProtocolRecent','vhBackendProtocolUnobserved']) assert(en[key] && pl[key]);
|
|
const badge = (vhost, backend) => ({dataset:{upstreamProtocolVhost:vhost,upstreamProtocolBackend:backend},textContent:'',title:''});
|
|
const visible = [badge('api','auto-backend'),badge('api','h1-backend'),badge('other','auto-backend')];
|
|
const envelope = {config:{vhosts:[
|
|
{id:'api',backends:[{id:'auto-backend',protocol:'auto'},{id:'h1-backend',protocol:'http1'}]},
|
|
{id:'other',backends:[{id:'auto-backend',protocol:'auto'}]},
|
|
]}};
|
|
const ctx = {Date, Number, String, Map, envelope, document:{querySelectorAll:()=>visible},t:key=>en[key]};
|
|
vm.createContext(ctx);
|
|
vm.runInContext(block, ctx);
|
|
const recent = Date.now() - 2000;
|
|
let status = {backend_pools:[{id:'api',members:[
|
|
{id:'auto-backend',upstream_protocol_observed:'h2',upstream_protocol_last_seen_ms:recent,upstream_protocol_http1_total:5,upstream_protocol_http2_total:9},
|
|
{id:'h1-backend',upstream_protocol_observed:'h1',upstream_protocol_last_seen_ms:recent,upstream_protocol_http1_total:12},
|
|
]}]};
|
|
ctx.renderUpstreamProtocolBadges(status);
|
|
assert.equal(visible[0].textContent,'auto-backend · AUTO → H2');
|
|
assert.equal(visible[0].dataset.observed,'true');
|
|
assert(visible[0].title.includes('H1: 5; H2: 9'));
|
|
assert.equal(visible[1].textContent,'h1-backend · H1 → H1');
|
|
assert.equal(visible[2].textContent,'auto-backend · AUTO → ?');
|
|
assert.equal(visible[2].dataset.observed,'false');
|
|
// Old/stale response must not masquerade as a recent ALPN observation.
|
|
status.backend_pools[0].members[0].upstream_protocol_last_seen_ms = Date.now() - 3600000;
|
|
ctx.renderUpstreamProtocolBadges(status);
|
|
assert.equal(visible[0].textContent,'auto-backend · AUTO → ?');
|
|
assert.equal(visible[0].dataset.observed,'false');
|
|
assert(visible[0].title.startsWith(en.vhBackendProtocolUnobserved));
|
|
// Fresh data for a similarly named backend from another vhost must not leak.
|
|
ctx.renderUpstreamProtocolBadges({backend_pools:[{id:'other',members:[
|
|
{id:'auto-backend',upstream_protocol_observed:'h1',upstream_protocol_last_seen_ms:recent}
|
|
]}]});
|
|
assert.equal(visible[0].textContent,'auto-backend · AUTO → ?');
|
|
assert.equal(visible[2].textContent,'auto-backend · AUTO → H1');
|
|
ctx.renderUpstreamProtocolBadges({backend_pools:[]});
|
|
assert.equal(visible[2].textContent,'auto-backend · AUTO → ?');
|
|
console.log('PASS: observed Auto/H1/H2 badges, freshness, cross-vhost isolation and unknown data');
|