Files
gods-eye-view/scripts/qa-military-names.mjs
T
German Khokhlov 0459ee6d58 Scope render demand to each scene attachment
Give each scene its own render governor, owner holds and recent idle requests.
Make the Cesium render backend own its request mode directly, so the governor
drives engine.render on both engines without a dependency back from Cesium.
Route layer requests through their attached engine and capture the attachment's
governor for camera motions, orbit, annotations and shell controls. Release
retained-layer holds before clearing the outgoing engine, and destroy the
governor after scene consumers have detached.

Preserve Cesium's owner-keyed holds, pre-install buffering, last-release settling
frame and one-shot requests during continuous rendering. Navara keeps the same
render policy. There is no intended visible change on either engine. Simultaneous
scenes no longer share holds, and an old captured service cannot release a
replacement attachment's hold. Cover both rules on fake and headless Cesium
engines, including an old orbit ending after reattachment.

Viewer-reference lines fall from 910 to 891, Navara-kind checks from 2 to 1,
and engine-name lines from 33 to 32. All other coupling counts stay unchanged.

Checked in the browser, keyless: qa-perf passes on both engines with the
same idle, active and release counts as before (24 checks on Cesium, 22 on
Navara).
2026-11-07 16:56:34 +04:00

486 lines
16 KiB
JavaScript

#!/usr/bin/env node
/** Named military areas: continent performance, close identities and a recorded zoom. */
import assert from 'node:assert/strict';
import fs from 'node:fs/promises';
import puppeteer from 'puppeteer';
import {
checkInstallationPan,
checkInstallationSelection,
} from './qa-installation-polish.mjs';
import {
createScreencast,
installFrameProbe,
readFrames,
frameStats,
pageNow,
moveCamera,
} from './qa-journey-recorder.mjs';
const args = process.argv.slice(2);
if (args.includes('--help')) {
console.log('Usage: node scripts/qa-military-names.mjs <url> [--no-video]');
process.exit(0);
}
const url = args.find((a) => /^https?:/.test(a));
if (!url) throw new Error('Supply the running server URL');
const dir = process.env.QA_NAMES_DIR || 'qa-shots/military-names';
await fs.mkdir(dir, { recursive: true });
const result = {
views: [],
sites: [],
errors: [],
forbidden: [],
packs: [],
video: null,
};
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const browser = await puppeteer.launch({
headless: true,
protocolTimeout: 180000,
args: [
'--use-angle=metal',
'--disable-background-timer-throttling',
'--disable-renderer-backgrounding',
],
});
let recorder;
try {
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 800 });
page.on('pageerror', (e) => result.errors.push(e.message));
page.on('console', (m) => {
if (m.type() === 'error') result.errors.push(m.text());
});
page.on('request', (request) => {
const u = new URL(request.url());
if (
/overpass/i.test(u.hostname) ||
u.hostname === 'nominatim.openstreetmap.org'
)
result.forbidden.push(u.origin);
if (u.pathname.endsWith('/osm_military_names/names.json'))
result.packs.push(u.pathname);
});
await page.evaluateOnNewDocument(() =>
sessionStorage.setItem('gev:first-run-mission-session:v1', 'dismissed'),
);
await page.goto(url + (url.includes('?') ? '&' : '?') + 'welcome=0', {
waitUntil: 'domcontentloaded',
});
await page.waitForFunction(
() =>
window.__godsEyeView?.dataManager &&
document.getElementById('loading-screen')?.classList.contains('hidden'),
{ timeout: 120000 },
);
await page.evaluate(
() => window.__godsEyeView.styleManager.initialRestorePromise,
);
await page.keyboard.press('Escape');
result.page = await page.evaluate(() => ({
url: location.href,
title: document.title,
canvas: Boolean(document.querySelector('#cesiumContainer canvas')),
errorOverlay: Boolean(document.querySelector('vite-error-overlay')),
}));
assert.equal(new URL(result.page.url).origin, new URL(url).origin);
assert.ok(
result.page.title && result.page.canvas && !result.page.errorOverlay,
);
await page.evaluate(async () => {
const g = window.__godsEyeView;
for (const [id] of g.dataManager.layers)
await g.dataManager.setEnabled(id, false);
g.styleManager.setDetection({ enabled: false });
g.viewer.scene.screenSpaceCameraController.enableCollisionDetection = false;
});
assert.equal(result.packs.length, 0, 'names pack stays unloaded at startup');
result.renderer = await page.evaluate(() => {
const gl = window.__godsEyeView.viewer.scene.context._gl;
const ext = gl.getExtension('WEBGL_debug_renderer_info');
return ext
? gl.getParameter(ext.UNMASKED_RENDERER_WEBGL)
: gl.getParameter(gl.RENDERER);
});
assert.doesNotMatch(result.renderer, /swiftshader|software/i);
await installFrameProbe(page);
const stats = () =>
page.evaluate(() =>
window.__godsEyeView.dataManager.layers
.get('military-installations')
.module.getStats(),
);
const settle = async () => {
await sleep(500);
await page.waitForFunction(
() => {
const s = window.__godsEyeView.dataManager.layers
.get('military-installations')
.module.getStats();
return !s.loading && s.count > 0 && s.status === 'ready';
},
{ timeout: 60000 },
);
await sleep(1200);
};
const us = { lon: -100, lat: 39, height: 6500000, pitch: -90 };
await moveCamera(page, us, 0);
await page.evaluate(() =>
window.__godsEyeView.dataManager.setEnabled('military-installations', true),
);
await settle();
result.credit = await page.evaluate(() => {
const el = document.querySelector('#cesium-credits');
return {
text: el?.innerText || '',
visible: Boolean(el && getComputedStyle(el).display !== 'none'),
};
});
assert.match(result.credit.text, /© OpenStreetMap/);
assert.doesNotMatch(
result.credit.text,
/© OpenMapTiles/,
'wide bundled names use no vector tiles',
);
assert.ok(result.credit.visible);
await page.screenshot({ path: `${dir}/credit.png` });
for (const [name, view] of [
['us', us],
['europe', { lon: 12, lat: 50, height: 4500000, pitch: -90 }],
]) {
await moveCamera(page, view, 2);
await settle();
const before = await stats();
const overlaps = await page.evaluate(async () => {
const { getOverlayPaintRect } =
await import('/src/overlays/worldOverlay.js');
const layer = window.__godsEyeView.dataManager.layers.get(
'military-installations',
).module;
const rects = [];
layer.visitNamedMarkers((id) => {
const rect = getOverlayPaintRect('military-installations', id);
if (rect) rects.push(rect);
});
let overlaps = 0;
for (let a = 0; a < rects.length; a++)
for (let b = a + 1; b < rects.length; b++) {
const x = rects[a],
y = rects[b];
if (
x.x < y.x + y.w &&
y.x < x.x + x.w &&
x.y < y.y + y.h &&
y.y < x.y + x.h
)
overlaps++;
}
return overlaps;
});
// Incumbents retain their placements during camera motion, as for Data Centers.
assert.ok(
before.namedInView > 0 &&
before.namedMarkers > 0 &&
before.pointsOnScreen > 0,
);
assert.ok(
before.labelsOnScreen > 0 && before.labelsOnScreen <= before.labelCap,
);
await page.evaluate(async () => {
// Use the governor's hold so an asynchronous idle transition cannot
// overwrite a raw scene flag during the sustained-render measurement.
const { holdContinuousRender } = await import('/src/renderGovernor.js');
holdContinuousRender('qa-military-names-fps', window.__godsEyeView.engine);
});
const t0 = await pageNow(page);
await sleep(3500);
const frames = await readFrames(page, t0);
await page.evaluate(async () => {
const { releaseContinuousRender } =
await import('/src/renderGovernor.js');
releaseContinuousRender('qa-military-names-fps', window.__godsEyeView.engine);
});
const metrics = frameStats(frames);
const seconds = frames.reduce((sum, frame) => sum + frame.dt, 0) / 1000;
const fps = metrics.renderedFrames / seconds;
const rafFps = metrics.frames / seconds;
result.views.push({ name, ...before, overlaps, fps, rafFps, ...metrics });
console.log(name, JSON.stringify(result.views.at(-1)));
await page.screenshot({ path: `${dir}/${name}.png` });
assert.ok(fps >= 55, `${name} fps ${fps.toFixed(1)} < 55`);
}
await page.evaluate(() =>
window.__godsEyeView.styleManager.setCleanView(true),
);
await sleep(300);
result.cleanUi = await page.evaluate(async () => {
const host = await import('/src/overlays/worldOverlay.js');
const root = document.getElementById('world-overlay-root');
return {
active: document.body.classList.contains('ui-clean-view'),
visible: root.checkVisibility({
visibilityProperty: true,
opacityProperty: true,
}),
labels:
host.getWorldOverlayDiagnostics().paintedBySource[
'military-installations'
] || 0,
};
});
assert.ok(
result.cleanUi.active &&
result.cleanUi.visible &&
result.cleanUi.labels > 0,
);
await page.screenshot({ path: `${dir}/clean-ui.png` });
await page.evaluate(() =>
window.__godsEyeView.styleManager.setCleanView(false),
);
await page.evaluate(() =>
window.__godsEyeView.dataManager.setEnabled(
'military-installations',
false,
),
);
result.disabled = await page.evaluate(async () => {
const host = await import('/src/overlays/worldOverlay.js');
return host.getWorldOverlayDiagnostics().entriesBySource[
'military-installations'
];
});
assert.equal(result.disabled, 0);
await page.evaluate(() =>
window.__godsEyeView.dataManager.setEnabled('military-installations', true),
);
await moveCamera(page, us, 1);
await settle();
result.slowPan = await checkInstallationPan(page, dir);
await moveCamera(page, us, 1);
await settle();
if (!args.includes('--no-video')) {
recorder = await createScreencast(page, `${dir}/us-to-san-diego`, {
fps: 24,
});
await recorder.start();
}
await page.evaluate(async () => {
const C = await import('/node_modules/cesium/Build/Cesium/index.js');
const { getOverlayPaintRect } =
await import('/src/overlays/worldOverlay.js');
const g = window.__godsEyeView;
const layer = g.dataManager.layers.get('military-installations').module;
const overlay = document.createElement('div');
overlay.id = 'installation-label-probe';
overlay.style.cssText =
'position:fixed;top:60px;left:360px;z-index:99999;background:#07121cdd;color:#fff;padding:8px 12px;font:13px monospace;pointer-events:none';
document.body.append(overlay);
const screen = new C.Cartesian2();
window.__installationFrames = [];
window.__stopInstallationFrames =
g.viewer.scene.postRender.addEventListener(() => {
const stats = layer.getStats();
const markers = [],
labels = [],
rects = [];
layer.visitNamedMarkers((id, point) => {
const rect = getOverlayPaintRect('military-installations', id);
if (rect) rects.push(rect);
const p = C.SceneTransforms.worldToWindowCoordinates(
g.viewer.scene,
point.position,
screen,
);
if (
point.show &&
p &&
p.x >= 0 &&
p.y >= 0 &&
p.x < 1280 &&
p.y < 800
) {
markers.push(id);
if (rect) labels.push(id);
}
});
let overlaps = 0;
for (let a = 0; a < rects.length; a++)
for (let b = a + 1; b < rects.length; b++) {
const x = rects[a],
y = rects[b];
if (
x.x < y.x + y.w &&
y.x < x.x + x.w &&
x.y < y.y + y.h &&
y.y < x.y + x.h
)
overlaps++;
}
const altitude = g.viewer.camera.positionCartographic.height;
window.__installationFrames.push({
t: performance.now(),
altitude,
markers,
labels,
paintedLabels: stats.labelsOnScreen,
overlaps,
loading: stats.loading,
wide: stats.wide,
});
overlay.textContent = `${(altitude / 1000).toFixed(1)} km | markers ${markers.length} | labels ${labels.length} / 24`;
});
});
const clipStart = await pageNow(page);
await sleep(1200);
for (const view of [
{ lon: -116, lat: 35, height: 1500000, pitch: -85 },
{ lon: -117.2, lat: 33, height: 200000, pitch: -80 },
{ lon: -117.1, lat: 32.86, height: 18000, pitch: -80 },
]) {
await moveCamera(page, view, 3);
await sleep(800);
}
await settle();
await sleep(1500);
result.clipFrames = await readFrames(page, clipStart);
result.labelFrames = await page.evaluate(() => {
window.__stopInstallationFrames();
document.getElementById('installation-label-probe').remove();
return window.__installationFrames;
});
await fs.writeFile(
`${dir}/label-frames.json`,
JSON.stringify(result.labelFrames, null, 2),
);
assert.ok(result.labelFrames.length > 100);
assert.ok(
result.labelFrames.every(
(frame) =>
frame.markers.length > 0 &&
frame.labels.length > 0 &&
frame.paintedLabels > 0 &&
frame.paintedLabels <= 24,
),
'zoom never loses all visible named markers or labels',
);
if (recorder) {
result.video = await recorder.stop();
recorder = null;
}
result.selection = await checkInstallationSelection(page, dir, {
video: !args.includes('--no-video'),
});
const sites = [
['mabry', 'Camp Mabry', -97.765, 30.3125, 3500],
['pendleton', 'Marine Corps Base Camp Pendleton', -117.4, 33.33, 25000],
['miramar', 'Marine Corps Air Station Miramar', -117.14, 32.87, 18000],
['ramstein', 'Ramstein Air Base', 7.6, 49.44, 7000],
['lakenheath', 'RAF Lakenheath', 0.56, 52.41, 7000],
['hood', 'Fort Hood', -97.78, 31.135, 30000],
];
for (const [key, expected, lon, lat, height] of sites) {
await moveCamera(page, { lon, lat, height, pitch: -80 }, 1.5);
await settle();
const snapshot = await page.evaluate(
(lat, lon) => {
const g = window.__godsEyeView;
const layer = g.dataManager.layers.get('military-installations').module;
const position = g.viewer.scene.globe.ellipsoid.cartographicToCartesian(
{
longitude: (lon * Math.PI) / 180,
latitude: (lat * Math.PI) / 180,
height: 0,
},
);
return {
stats: layer.getStats(),
records: layer.getNearby(position, 100000, 1000).map((r) => ({
id: r.id,
name: r.name,
memberNames: r.memberNames || [],
hasPolygon: Boolean(r.footprints?.length),
})),
};
},
lat,
lon,
);
result.sites.push({ key, expected, ...snapshot });
assert.equal(
new Set(snapshot.records.map((r) => r.id)).size,
snapshot.records.length,
);
assert.ok(
snapshot.stats.labelsOnScreen > 0 &&
snapshot.stats.labelsOnScreen <= snapshot.stats.labelCap,
);
assert.ok(
snapshot.records.some((r) => r.name === expected && r.hasPolygon),
`${key}: missing named polygon ${expected}; got ${snapshot.records.map((r) => r.name).join(', ')}`,
);
await page.screenshot({ path: `${dir}/${key}.png` });
console.log(key, expected);
}
await page.evaluate(() => {
if (
document
.getElementById('global-context-panel')
.classList.contains('collapsed')
)
document
.querySelector('[data-collapse-target="global-context-panel"]')
.click();
});
await page.waitForSelector('#global-context-flights-btn', { visible: true });
await page.evaluate(() => {
const button = document.getElementById('global-context-flights-btn');
if (button.getAttribute('aria-selected') !== 'true') button.click();
});
await page.waitForFunction(
() => {
const state = window.__godsEyeView.styleManager.getContextModeState();
return state.mode === 'flights' && !state.changing;
},
{ timeout: 60000 },
);
result.card = await page.evaluate(() => {
const g = window.__godsEyeView;
return g.dataManager.layers
.get('military-installations')
.module.focusById('osm:military:r13529728');
});
assert.equal(result.card, true);
await page.waitForFunction(
() =>
document
.getElementById('military-awareness-panel')
?.textContent.includes('Named areas') &&
document
.getElementById('military-awareness-panel')
.checkVisibility({ visibilityProperty: true, opacityProperty: true }),
{ timeout: 15000 },
);
result.cardText = await page.$eval(
'#military-awareness-panel',
(el) => el.textContent,
);
assert.match(result.cardText, /Fort Hood/);
assert.match(result.cardText, /TA-25/);
await sleep(1800);
await page.$eval(
'#military-awareness-panel .military-awareness-names',
(el) => {
el.open = true;
},
);
await page.screenshot({ path: `${dir}/member-names-card.png` });
assert.equal(result.packs.length, 1, 'single lazy asset fetch');
assert.deepEqual(result.forbidden, []);
assert.deepEqual(result.errors, []);
} finally {
if (recorder)
result.video = await recorder.stop().catch((e) => ({ error: e.message }));
await fs.writeFile(`${dir}/result.json`, JSON.stringify(result, null, 2));
await browser.close();
}