- 원인: 구조물을 새 측점에 놓으면 측점 갈아끼움(비동기)이 끝나기 전 묶음 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>
150 lines
6.0 KiB
Python
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}
|