Skip to content

Commit b6846a0

Browse files
committed
ni
1 parent 647c1d0 commit b6846a0

2 files changed

Lines changed: 96 additions & 9 deletions

File tree

Makefile

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ BUILD_DIR_DEPLOY := build-deploy
2424
BUILD_DIR_CODEGEN := build-codegen
2525
BUILD_DIR_WEBASM_YEMU := build-webasm-yemu-release
2626

27-
.PHONY: help all build-desktop-release build-desktop-debug build-desktop-asan build-linux-riscv64-release build-deploy build-yemu-release run-qemu build-webasm-yemu-release run-node run-codegen perf-picoforge perf-throughput-notracing perf-throughput-tracing clean
27+
.PHONY: help all build-desktop-release build-desktop-debug build-desktop-asan build-linux-riscv64-release build-deploy build-yemu-release run-qemu build-webasm-yemu-release run-node run-webserver run-codegen perf-picoforge perf-throughput-notracing perf-throughput-tracing clean
2828

2929
# AddressSanitizer flags. Frame pointers for readable traces; the same flags
3030
# go on compile AND link so the asan runtime is pulled in. The vendored static
@@ -178,6 +178,22 @@ run-node:
178178
fi
179179
node tools/picoforge/yemu/node/picomesh-vm.cjs $(NODE_ARGS)
180180

181+
## run-webserver serve the wasm bundle over HTTP with python
182+
## (the bundle's own serve.py, which sets the
183+
## COOP/COEP headers the wasm needs) — exactly how the
184+
## GitHub Pages deploy is served. Builds the bundle if
185+
## missing. Open http://127.0.0.1:$(WEBSERVER_PORT)/
186+
## and the page boots the VM + runs a startup smoke.
187+
## Override the port: make run-webserver WEBSERVER_PORT=9000
188+
WEBSERVER_PORT ?= 8000
189+
run-webserver:
190+
@if [ ! -f $(BUILD_DIR_WEBASM_YEMU)/picomesh-yemu.js ]; then \
191+
echo "==> wasm bundle missing — building it first"; \
192+
$(MAKE) build-webasm-yemu-release; \
193+
fi
194+
@echo "==> serving $(BUILD_DIR_WEBASM_YEMU) at http://127.0.0.1:$(WEBSERVER_PORT)/ (Ctrl-C to stop)"
195+
python3 $(BUILD_DIR_WEBASM_YEMU)/serve.py $(WEBSERVER_PORT) $(BUILD_DIR_WEBASM_YEMU)
196+
181197
## build-linux-riscv64-release cross-compile picomesh + picoforge-webapp for
182198
## riscv64 (static, for the yemu demo VM
183199
## or any riscv64 Linux target). Needs

tools/picoforge/yemu/web/tinyemu-iframe.html

Lines changed: 79 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -315,14 +315,11 @@ <h2>in-VM service</h2>
315315
ov.classList.add('minimized');
316316
tog.textContent = '+';
317317
}
318-
/* Auto-submit the default GET so the user lands on the
319-
* picoforge login page without having to click "GET". The
320-
* form defaults to port=8081 path=/-/login (the webapp HTML
321-
* tier; the gateway on :8080 serves no GET pages). */
322-
var form = document.getElementById('svc-form');
323-
if (form) {
324-
form.dispatchEvent(new Event('submit', { cancelable: true }));
325-
}
318+
/* Run the one-shot startup smoke: it waits for the gateway/backend,
319+
* exercises register/login/repos/create against :8081, reports
320+
* PASS/FAIL into this overlay, then leaves the app on /-/login so
321+
* the user can sign in. (Replaces the old bare auto-GET /-/login.) */
322+
runStartupSmoke();
326323
}
327324
window.__renderStatus = function (text, level, tag) {
328325
var d = document.createElement('div');
@@ -932,6 +929,80 @@ <h2>in-VM service</h2>
932929
return current;
933930
}
934931

932+
/* ---- one-shot startup smoke ------------------------------------
933+
* Runs ONCE when the in-VM webapp comes up (kicked from
934+
* revealService). Waits for the gateway/backend to answer, then drives
935+
* the real endpoints through the slirp bridge — register a throwaway
936+
* user (picomesh auto-logs-in), confirm the authenticated /-/repos, and
937+
* create a repo — reporting PASS/FAIL into the boot overlay. No
938+
* clicking: open the page (make run-webserver) and watch it go green.
939+
* It leaves the app on /-/login so the user can sign in afterwards. */
940+
var smokeStarted = false;
941+
function smokeLine(text, ok) {
942+
var d = document.createElement('div');
943+
d.className = ok === true ? 'ok' : ok === false ? 'err' : '';
944+
d.textContent = (ok === true ? ' PASS: ' : ok === false ? ' FAIL: ' : '[smoke] ') + text;
945+
body.appendChild(d);
946+
body.scrollTop = body.scrollHeight;
947+
console.log('[smoke]', (ok === undefined ? '' : (ok ? 'PASS ' : 'FAIL ')) + text);
948+
}
949+
function smokeBodyText(resp) {
950+
try { return new TextDecoder('utf-8', { fatal: false }).decode(resp.body || new Uint8Array(0)); }
951+
catch (e) { return ''; }
952+
}
953+
async function runStartupSmoke() {
954+
if (smokeStarted) return;
955+
smokeStarted = true;
956+
var PORT = 8081; // the picoforge webapp HTML tier
957+
// Make the webapp the active port so the user's manual login/nav
958+
// (picomesh-submit / picomesh-nav handlers gate on svcLastPort > 0)
959+
// work after boot — this replaced the old auto-GET that used to set
960+
// it. Without this, every login/click is silently "ignored".
961+
svcLastPort = PORT;
962+
var loggedIn = /Sign out|\/-\/logout/;
963+
smokeLine('startup smoke: waiting for webapp :' + PORT + ' …');
964+
965+
// 1. Wait for the gateway/backend to be up (GET /-/login -> 200).
966+
var up = false;
967+
for (var i = 0; i < 150 && !up; i++) {
968+
try { var r = await svcFetchOnce(PORT, '/-/login'); if (r.status === 200) up = true; }
969+
catch (e) { /* not up yet */ }
970+
if (!up) await new Promise(function (res) { setTimeout(res, 2000); });
971+
}
972+
smokeLine('webapp serves GET /-/login (200)', up);
973+
if (!up) { smokeLine('STARTUP SMOKE ABORTED — backend never came up', false); return; }
974+
975+
var pass = 1, total = 1;
976+
function tally(ok) { total++; if (ok) pass++; return ok; }
977+
try {
978+
// 2. Register a throwaway user; picomesh auto-logs-in (303 + sid).
979+
var u = 'smoke' + (Date.now() % 1000000);
980+
var reg = await followFromResp(PORT,
981+
await svcFetchWithMethod(PORT, 'POST', '/-/register', 'username=' + u + '&password=pw'), 5);
982+
smokeLine('register ' + u + ' + auto-login (session established)',
983+
tally(reg.status === 200 && loggedIn.test(smokeBodyText(reg))));
984+
985+
// 3. The session persists: authenticated /-/repos shows the shell.
986+
var repos = await svcFetchOnce(PORT, '/-/repos');
987+
smokeLine('authenticated GET /-/repos (logged in)',
988+
tally(repos.status === 200 && loggedIn.test(smokeBodyText(repos))));
989+
990+
// 4. Create a repo: POST /-/repos/new -> 303 -> repo tree page.
991+
var mk = await followFromResp(PORT,
992+
await svcFetchWithMethod(PORT, 'POST', '/-/repos/new', 'name=smoke-repo'), 5);
993+
smokeLine('create repo ' + u + '/smoke-repo',
994+
tally(mk.status === 200 && /smoke-repo/.test((mk.path || '') + smokeBodyText(mk))));
995+
} catch (e) {
996+
smokeLine('smoke error: ' + (e && e.message ? e.message : e), false);
997+
}
998+
smokeLine('STARTUP SMOKE ' + (pass === total ? 'PASS' : 'FAIL') +
999+
' — ' + pass + '/' + total + ' checks', pass === total);
1000+
1001+
// Leave the user on the login page (the smoke registered its own
1002+
// throwaway account; logging in below replaces that cookie).
1003+
try { renderResp(PORT, await svcFetchOnce(PORT, '/-/login')); } catch (e) { /* ignore */ }
1004+
}
1005+
9351006
async function svcGo(ev) {
9361007
ev.preventDefault();
9371008
if (typeof Module === 'undefined' || !Module._tinyemu_session_open) {

0 commit comments

Comments
 (0)