f2babb36
test(wan): named sessions over the real link
a73x 2026-08-15 12:22
Commit message
test/wan.sh
| Old | New | ||
|---|---|---|---|
| @@ -1297,8 +1297,105 @@ if [ "${MUX_WAN_PREDICT:-}" = "1" ]; then | |||
| 1297 | netem_off | 1297 | netem_off |
| 1298 | fi | 1298 | fi |
| 1299 | 1299 | ||
| 1300 | # ---- M18: named sessions over the real link ------------------------------- | ||
| 1301 | # Everything above drives the DEFAULT session, because everything above | ||
| 1302 | # predates M18. This is the leg that asks whether a session NAME survives a | ||
| 1303 | # real link — not a loopback, not a container bridge. Three claims, each its | ||
| 1304 | # own assertion: two named sessions on one remote daemon hold only their own | ||
| 1305 | # content; the default session holds neither; and re-attaching BY NAME lands | ||
| 1306 | # back in the shell that name already had rather than in a fresh one. | ||
| 1307 | # | ||
| 1308 | # Deliberately placed after every measurement above. It leaves two more | ||
| 1309 | # shells on the box, and a session that exists is a session the timing legs | ||
| 1310 | # would otherwise have shared a daemon with. | ||
| 1311 | # | ||
| 1312 | # Those two shells are left behind ON PURPOSE and re-running is safe, which | ||
| 1313 | # is worth saying because "leaves sessions on the box" reads as a leak. The | ||
| 1314 | # daemon here is this run's own ($RBIN on $RSOCK, torn down with it), so | ||
| 1315 | # nothing outlives the harness. And within a run the leg is idempotent by | ||
| 1316 | # construction: attach-or-create REJOINS `a` and `b` rather than failing on | ||
| 1317 | # them, and every marker carries $$, so a grid left by an earlier run can | ||
| 1318 | # never satisfy a later run's grep. | ||
| 1319 | say "M18: named sessions over the real link" | ||
| 1320 | M18_OK=1 | ||
| 1321 | M18_N="$$" | ||
| 1322 | for S in a b; do | ||
| 1323 | # A marker the REMOTE shell has to expand: the typed line carries a | ||
| 1324 | # literal %s, so the joined form can only exist if bash on the box ran | ||
| 1325 | # printf. An echo of our own keystrokes cannot satisfy the greps below. | ||
| 1326 | { printf 'printf "wansess-%s-%%s\\n" %s\n' "$S" "$M18_N"; sleep 3; printf '\034'; } | \ | ||
| 1327 | timeout 90 "$MUX" --via "$VIA" --session "$S" > "$WORK/m18-$S.out" 2>&1 | ||
| 1328 | rc=$? | ||
| 1329 | if [ "$rc" -ne 0 ]; then | ||
| 1330 | echo " FAIL: --session $S over --via exited $rc" | ||
| 1331 | sed -n '1,3p' "$WORK/m18-$S.out" | ||
| 1332 | M18_OK=0 | ||
| 1333 | fi | ||
| 1334 | done | ||
| 1335 | |||
| 1336 | if [ "$M18_OK" -eq 1 ]; then | ||
| 1337 | A_GRID="$(timeout 60 $MUX_WAN_SSH "$RBIN dump --sock $RSOCK --session a" 2>/dev/null)" | ||
| 1338 | B_GRID="$(timeout 60 $MUX_WAN_SSH "$RBIN dump --sock $RSOCK --session b" 2>/dev/null)" | ||
| 1339 | D_GRID="$(timeout 60 $MUX_WAN_SSH "$RBIN dump --sock $RSOCK" 2>/dev/null)" | ||
| 1340 | |||
| 1341 | # Positive AND negative per session: "a holds a's marker" is satisfied | ||
| 1342 | # just as well by one shared shell, so only the negative separates them. | ||
| 1343 | case "$A_GRID" in *"wansess-a-$M18_N"*) ;; *) | ||
| 1344 | echo " FAIL: session a's marker is not on session a's grid"; M18_OK=0 ;; esac | ||
| 1345 | case "$A_GRID" in *"wansess-b-$M18_N"*) | ||
| 1346 | echo " FAIL: session b's marker is on session a's grid — one shell, not two" | ||
| 1347 | M18_OK=0 ;; esac | ||
| 1348 | case "$B_GRID" in *"wansess-b-$M18_N"*) ;; *) | ||
| 1349 | echo " FAIL: session b's marker is not on session b's grid"; M18_OK=0 ;; esac | ||
| 1350 | case "$B_GRID" in *"wansess-a-$M18_N"*) | ||
| 1351 | echo " FAIL: session a's marker is on session b's grid — one shell, not two" | ||
| 1352 | M18_OK=0 ;; esac | ||
| 1353 | # The default session is the one every leg above drove. Neither name may | ||
| 1354 | # have leaked into it. | ||
| 1355 | case "$D_GRID" in *"wansess-a-$M18_N"*|*"wansess-b-$M18_N"*) | ||
| 1356 | echo " FAIL: a named session's marker reached the default grid"; M18_OK=0 ;; esac | ||
| 1357 | fi | ||
| 1358 | |||
| 1359 | if [ "$M18_OK" -eq 1 ]; then | ||
| 1360 | # Re-attach by name: this must JOIN the shell `a` already has. The proof | ||
| 1361 | # is both markers on one grid afterwards — a fresh shell would carry the | ||
| 1362 | # new marker alone, which is exactly the failure a name that resolved | ||
| 1363 | # per-connection would produce. | ||
| 1364 | { printf 'printf "wanre-%%s\\n" %s\n' "$M18_N"; sleep 3; printf '\034'; } | \ | ||
| 1365 | timeout 90 "$MUX" --via "$VIA" --session a > "$WORK/m18-re.out" 2>&1 | ||
| 1366 | rc=$? | ||
| 1367 | if [ "$rc" -ne 0 ]; then | ||
| 1368 | echo " FAIL: re-attach to session a exited $rc"; M18_OK=0 | ||
| 1369 | else | ||
| 1370 | A2="$(timeout 60 $MUX_WAN_SSH "$RBIN dump --sock $RSOCK --session a" 2>/dev/null)" | ||
| 1371 | case "$A2" in *"wanre-$M18_N"*) ;; *) | ||
| 1372 | echo " FAIL: the re-attach's own marker never reached session a"; M18_OK=0 ;; esac | ||
| 1373 | case "$A2" in *"wansess-a-$M18_N"*) ;; *) | ||
| 1374 | echo " FAIL: re-attaching to 'a' found a FRESH shell, not the one it named" | ||
| 1375 | M18_OK=0 ;; esac | ||
| 1376 | # ...and it joined rather than created: a fourth session here would | ||
| 1377 | # mean the name resolved per-connection. | ||
| 1378 | M18_STATS="$(timeout 60 $MUX_WAN_SSH "$RBIN stats --sock $RSOCK" 2>/dev/null)" | ||
| 1379 | case "$M18_STATS" in *"sessions=3"*) ;; *) | ||
| 1380 | echo " FAIL: re-attach by name changed the session count: $M18_STATS" | ||
| 1381 | M18_OK=0 ;; esac | ||
| 1382 | fi | ||
| 1383 | fi | ||
| 1384 | |||
| 1385 | if [ "$M18_OK" -eq 1 ]; then | ||
| 1386 | echo " two named sessions isolated over the link; re-attach by name rejoined" | ||
| 1387 | echo " its own shell; default session untouched; sessions=3" | ||
| 1388 | fi | ||
| 1389 | |||
| 1300 | # ---- summary + the kill criterion ----------------------------------------- | 1390 | # ---- summary + the kill criterion ----------------------------------------- |
| 1301 | FAILED=0 | 1391 | FAILED=0 |
| 1392 | # M18's leg is a functional gate, not a measured one. It is deliberately | ||
| 1393 | # kept OUT of $FAILED: that variable drives the "kill criteria (M6 + M7)" | ||
| 1394 | # line, and a named-session failure is not an M6 or M7 failure. Reported | ||
| 1395 | # on its own below, and folded into the exit status there. (The first | ||
| 1396 | # version of this did set FAILED, and the falsification run printed | ||
| 1397 | # "kill criteria (M6 + M7): FAIL" for a defect in neither — which is how | ||
| 1398 | # the mistake was found.) | ||
| 1302 | 1399 | ||
| 1303 | phase_block() { | 1400 | phase_block() { |
| 1304 | local phase="$1" label="$2" | 1401 | local phase="$1" label="$2" |
| @@ -1458,10 +1555,13 @@ if [ "${MUX_WAN_QUIC:-}" = "1" ]; then | |||
| 1458 | echo " client slots held at peak during tears: $q_clients" | 1555 | echo " client slots held at peak during tears: $q_clients" |
| 1459 | fi | 1556 | fi |
| 1460 | echo | 1557 | echo |
| 1558 | if [ "${M18_OK:-1}" -eq 1 ]; then | ||
| 1559 | echo "M18 named sessions over the link: PASS" | ||
| 1560 | else | ||
| 1561 | echo "M18 named sessions over the link: FAIL" | ||
| 1562 | fi | ||
| 1461 | if [ "$FAILED" -eq 0 ]; then | 1563 | if [ "$FAILED" -eq 0 ]; then |
| 1462 | 1564 | echo "kill criteria (M6 + M7): PASS" | |
| 1463 | |||
| 1464 | echo "kill criteria (M6 + M7): PASS" | ||
| 1465 | else | 1565 | else |
| 1466 | echo "kill criteria (M6 + M7): FAIL — report the numbers; do not tune the thresholds." | 1566 | echo "kill criteria (M6 + M7): FAIL — report the numbers; do not tune the thresholds." |
| 1467 | fi | 1567 | fi |
| @@ -1557,4 +1657,6 @@ if [ -n "$(val predict predict med)" ]; then | |||
| 1557 | fi | 1657 | fi |
| 1558 | fi | 1658 | fi |
| 1559 | echo "==================================================================" | 1659 | echo "==================================================================" |
| 1660 | # Either gate can fail the run; neither speaks for the other. | ||
| 1661 | [ "${M18_OK:-1}" -eq 1 ] || FAILED=1 | ||
| 1560 | exit "$FAILED" | 1662 | exit "$FAILED" |