Files
Aislo/resources/tester/test_272_swap_keeps_canon.py
T
eomsangdonandClaude Opus 5.5 f4a7b183b0 fix(평면): 새 구조물 측점 놓는 즉시 평면 비탈 끝 · 면적 = 저장 뒤 — 튐 없음 · 옮김 계획고 (PLAN 583-1 · 요구 441)
- 원인: 구조물을 새 측점에 놓으면 측점 갈아끼움(비동기)이 끝나기 전 묶음 cross 단계가 옛 상세를 봐 엔진 길로 빠짐 — 구조물 얹기 없는 한 차례(벽 측점 비탈 끝 35 · 55 m · 기존 벽 측점 18.96 m)가 약 80 ms 평면에 튐 · 다음 차례(0.25 s)에 저장 값
- design_shared savedCross = 도는 갈아끼움(swapInFlight)을 기다려 그 상세로 다시 셈 · 상세 가게 swapInFlight 새로
- 종단도 listed() 옛 측점 = 저장 정본 상세 — 갈아끼운 상세로 셈해 옮긴 구조물 옛 측점 꼭짓점이 안 옮겨져 계획고 최대 2.4 cm 갈리던 것(옮김 면적 차 0.17 → 0.0175 ㎡)
- 시험: test_272_swap_keeps_canon 에 도는 갈아끼움 기다림 · test_473_lane_ready 글 대조를 새 호출 꼴로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 15:05:16 +09:00

150 lines
6.0 KiB
Python

# -*- coding: utf-8 -*-
"""467 (요구 272 · 분석 4장 (B1)) — 노선 초안 없는 차례의 갈아끼움이 정본 횡단을 지킴.
못박는 것
- 관만 옮김(노선 초안 없음) — 같은 열쇠 · 누가거리 0.01 m 안 측점은 앞 횡단(서버 정본)
기하 · 표본 · 중심고 그대로(R 12 곡선 축 차 3.3e-4 · 중심 0.5 mm 차여도) ·
옮긴 관 측점만 브라우저 표본.
- 되돌림(관 제자리) — 관 측점 밖 모든 횡단이 정본과 바이트 같음(관 측점 = 브라우저 표본).
- 노선 초안 차례 = 옛 규칙(축 허용 1e-4 · 넘으면 브라우저 표본).
- 가게 길(`swapSectionStations`) = 가게 `routeDraft` 로 가름 — 없음 · 있음 ·
초안 버린 직후(초안 표본이 안 남음).
- 583 — 도는 갈아끼움 = `swapInFlight`(묶음 cross 단계가 기다림) · 끝나면 비움.
Node 헬퍼 `helper_272_swap_canon.mjs` 가 vite ssr 로 묶은 진짜 모듈을 부름.
"""
import json
import shutil
import subprocess
from pathlib import Path
import pytest
HERE = Path(__file__).resolve().parent
ROOT = HERE.parents[1]
CURVES = ("27.50", "33.20", "38.90")
STRAIGHT = ("0.00", "20.00", "40.00", "60.00", "70.00")
STILL = (*STRAIGHT, *CURVES)
@pytest.fixture(scope="module")
def out(tmp_path_factory):
work = tmp_path_factory.mktemp("b272swap")
build = subprocess.run( # noqa: S603 — 고정 실행 파일
[
"node",
str(ROOT / "config" / "node_modules" / "vite" / "bin" / "vite.js"),
"build",
"--configLoader",
"runner",
"--ssr",
"../resources/tester/helper_272_swap_canon_entry.ts",
"--outDir",
str(work),
"--logLevel",
"error",
],
cwd=ROOT,
capture_output=True,
text=True,
encoding="utf-8",
timeout=300,
)
assert build.returncode == 0, build.stderr
bundle = work / "bundle.mjs"
shutil.copy(work / "helper_272_swap_canon_entry.js", bundle)
proc = subprocess.run( # noqa: S603
["node", str(HERE / "helper_272_swap_canon.mjs"), str(bundle)],
cwd=ROOT,
capture_output=True,
text=True,
encoding="utf-8",
timeout=120,
)
assert proc.returncode == 0, proc.stderr
return json.loads(proc.stdout)
def test_관만_옮김_정본_기하_표본_그대로(out):
keep = out["pure"]["keep"]
for at in STILL:
assert keep[at]["same"], at # 곡선 축 차 3.3e-4 여도 서버 표본 · 기하
assert keep[at]["mark"] == f"canon@{float(at):g}"
assert keep["55.00"]["browser"] and not keep["55.00"]["same"] # 옮긴 관 = 새 자리 표본
assert out["pure"]["keepMoved"] is False # 「노선 밖 고침」 셈 그대로(0.01 m)
assert out["pure"]["defaultIsKeep"] # 기본 = 노선 초안 없음
def test_되돌림_정본과_바이트_같음(out):
back = out["pure"]["back"]
assert all(back[at]["same"] for at in STILL)
assert out["pure"]["backBytes"] # 관 측점 밖 횡단 = 정본 바이트
assert back["45.00"]["browser"] # 관 측점 = 브라우저 표본(정본은 저장 뒤 서버 값)
def test_격자에_구조물_놓고_뺌_같은_자리_정본(out):
g = out["gridStructure"]
assert (
g["placed"]["same"] and not g["placed"]["browser"]
) # 열쇠 바뀜(구조물) · 같은 자리 = 정본
assert g["removed"]["same"] and not g["removed"]["browser"] # 다시 격자 = 정본 표본 · 기하
assert g["removedBytes"]
def test_노선_초안_차례는_옛_규칙(out):
draft = out["pure"]["draft"]
for at in CURVES: # 축 차 > 1e-4 = 새 표본
assert draft[at]["browser"] and not draft[at]["same"], at
for at in STRAIGHT: # 축 차 1e-5 · 자리 같음 = 앞 표본(기하는 새 틀)
assert not draft[at]["browser"] and not draft[at]["same"], at
def test_가게_길_초안_없음(out):
s = out["storeNoDraft"]
assert s["moved"] and s["back"]
assert all(s["moved"][at]["same"] for at in STILL)
assert all(s["back"][at]["same"] for at in STILL) and s["backBytes"]
def test_가게_길_초안_있음_버린_직후(out):
s = out["storeDraft"]
assert s["routeDraftSet"]
for at in CURVES: # 초안이 옮긴 곡선 = 새 표본
assert s["draft"][at]["browser"], at
for at in STRAIGHT: # 초안 차례 = 옛 규칙(기하 새 틀 · 표본 앞 값)
assert not s["draft"][at]["same"] and not s["draft"][at]["browser"], at
dropped = s["dropped"]
for at in (
CURVES
): # 버린 뒤 = 저장 정본 자리 · 표본(초안 3 cm 자리 표본이 안 남음 · 467 덧 정본 물러섬)
assert dropped[at]["same"] and not dropped[at]["browser"], at
for at in STRAIGHT: # 초안이 안 옮긴 측점 = 앞 횡단 표본(서버) 그대로
assert not dropped[at]["browser"], at
def test_옮겼다_제자리_관_측점_정본(out):
p = out["pipeBack"]
assert p["pipe"]["same"] and not p["pipe"]["browser"] # 저장 정본 표본 · 기하
assert p["bytes"] # 관 밖 횡단 = 정본 바이트(관 설계 = 옮김 규칙 · 다시 셈 입력은 정본 물러섬)
def test_일반_측점_자리_관_지움_다른_목록(out):
g = out["pipeGone"]
assert g["placedKind"] == "irregular"
assert g["same"] is False # 관 카드 → 일반 측점 = 갈아끼움
assert g["sameUntouched"] is True # 일반 측점 그대로 = 같은 목록
assert g["culvertLeft"] is False and g["kind"] == "regular" # 관 카드 안 남음
assert g["canon"] # 그 자리 정본 표본 · 기하
def test_관_지움_되돌림_정본_설계(out):
r = out["pipeRestore"]
assert r["design"] and r["copy"] # 지우기 전 설계(정본 사본) — 빈 기본 설계 아님(472 덧)
assert r["place"] and r["bytes"]
assert r["bareFresh"]
def test_583_도는_갈아끼움_기다림(out):
assert out["inFlight"] == {"same": True, "again": True, "cleared": True}