- Source.stations · cross_section: 경로 칸 null · 파일 없음 · 절대 경로 · 옛 정수 m 이름이면 find_cross_file 로 찾음 · 그래도 없으면 「횡단 없음」(stations 에서 빠짐 · cross_section KeyError) · missing_stations 추가 - copy_stability: 같은 검사 → manifest missing_cross_chainages · warnings · E01 생성 응답 warnings - 실측: 검증 프로젝트 14 복사 모두 stations 성공 · 검증_브레인232 null 1 행(359 m) 살림 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
122 lines
4.6 KiB
Python
122 lines
4.6 KiB
Python
"""532-1 덧 · 요구 351 — E01 복사본 읽기가 횡단 경로 null · 파일 없음 · 옛 꼴에서도 돎.
|
|
|
|
- 경로 null · 경로 파일 없음 → B06 이름 규칙(`find_cross_file`)으로 찾음
|
|
- 옛 꼴 — 절대 경로(원본 쪽을 읽지 않음) · 소수 측점의 옛 정수 m 이름 · data 없음
|
|
- 어디에도 없으면 그 측점만 빠짐(`missing_stations`) · cross_section 은 KeyError
|
|
- 생성 복사(`copy_stability`)가 같은 검사 → manifest `missing_cross_chainages` · `warnings`
|
|
"""
|
|
|
|
import asyncio
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
|
|
|
|
from common_util import common_util_project_copy as cp # noqa: E402
|
|
from E01_StabRegister import E01_StabRegister_Source as src # noqa: E402
|
|
|
|
CROSS = "B06_Section/cross_sections"
|
|
|
|
|
|
def _cross(root: Path, name: str, label: str) -> None:
|
|
path = root / CROSS / name
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text(json.dumps({"label": label, "samples": [{"offset_m": 0}]}), encoding="utf-8")
|
|
|
|
|
|
def _row(chainage, path, data=..., seq=0):
|
|
design = {"design": {"ground_type": "soil"}}
|
|
return {
|
|
"chainage_m": chainage,
|
|
"sequence_num": seq,
|
|
"cross_section_file_path": path,
|
|
"data": json.dumps(design) if data is ... else data,
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def root(tmp_path):
|
|
outside = tmp_path / "original" / CROSS / "cross_00040m.json"
|
|
outside.parent.mkdir(parents=True)
|
|
outside.write_text(json.dumps({"label": "원본"}), encoding="utf-8")
|
|
copy = tmp_path / "copy"
|
|
_cross(copy, "cross_00000m.json", "정상")
|
|
_cross(copy, "cross_00020m.json", "null")
|
|
_cross(copy, "cross_00030m.json", "경로 틀림")
|
|
_cross(copy, "cross_00040m.json", "절대")
|
|
_cross(copy, "cross_00050m.json", "옛 정수") # 49.8 m 측점의 옛 이름
|
|
rows = [
|
|
_row(0.0, f"{CROSS}/cross_00000m.json"),
|
|
_row(20.0, None, seq=None),
|
|
_row(30.0, f"{CROSS}/cross_gone.json"),
|
|
_row(40.0, str(outside)),
|
|
_row(49.8, None, data=None),
|
|
_row(60.0, None), # 어디에도 없음
|
|
_row(None, None), # 누가거리 없는 행 — 측점 아님
|
|
]
|
|
(copy / src.STABILITY_DB_NAME).write_text(
|
|
json.dumps({"cross_sections": rows}), encoding="utf-8"
|
|
)
|
|
(copy / src.MANIFEST_NAME).write_text("{}", encoding="utf-8")
|
|
return copy
|
|
|
|
|
|
def test_stations_skip_only_missing(root):
|
|
got = src.stations(root)
|
|
assert [s["chainage_m"] for s in got] == [0.0, 20.0, 30.0, 40.0, 49.8]
|
|
assert [s["label"] for s in got] == ["정상", "null", "경로 틀림", "절대", "옛 정수"]
|
|
assert got[0]["ground_type"] == "soil" and got[4]["ground_type"] is None
|
|
assert src.missing_stations(root) == [60.0]
|
|
|
|
|
|
def test_cross_section(root):
|
|
assert src.cross_section(root, 20.0)["label"] == "null"
|
|
assert src.cross_section(root, 40.0)["label"] == "절대" # 원본 쪽 파일 아님
|
|
assert src.cross_section(root, 49.8)["design"] == {}
|
|
with pytest.raises(KeyError, match="횡단 없음"):
|
|
src.cross_section(root, 60.0)
|
|
with pytest.raises(KeyError, match="측점 없음"):
|
|
src.cross_section(root, 70.0)
|
|
|
|
|
|
def test_normal_copy_has_no_missing(root):
|
|
db = json.loads((root / src.STABILITY_DB_NAME).read_text(encoding="utf-8"))
|
|
db["cross_sections"] = db["cross_sections"][:1]
|
|
(root / src.STABILITY_DB_NAME).write_text(json.dumps(db), encoding="utf-8")
|
|
assert [s["label"] for s in src.stations(root)] == ["정상"]
|
|
assert src.missing_stations(root) == []
|
|
|
|
|
|
def test_copy_stability_warns(tmp_path, monkeypatch):
|
|
source = tmp_path / "source"
|
|
_cross(source, "cross_00000m.json", "a")
|
|
_cross(source, "cross_00020m.json", "b")
|
|
dump = {
|
|
"project": {"storage_path": "x"},
|
|
"surface_params": {"source_filter": "none"},
|
|
"route": None,
|
|
"cross_sections": [
|
|
_row(0.0, None),
|
|
_row(20.0, f"{CROSS}/cross_00020m.json"),
|
|
_row(35.5, None),
|
|
],
|
|
"route_points": [],
|
|
"longitudinal_sections": [],
|
|
}
|
|
|
|
async def fake_rows(connection, source_id):
|
|
return dump
|
|
|
|
monkeypatch.setattr(cp, "_stability_rows", fake_rows)
|
|
monkeypatch.setattr(cp, "resolve_stored_project_path", lambda _: str(source))
|
|
manifest = asyncio.run(cp.copy_stability(None, "s" * 36, "e" * 36, tmp_path / "e"))
|
|
assert manifest["missing_cross_chainages"] == [35.5]
|
|
assert manifest["warnings"] == ["횡단 없는 측점 1 개 — 해석에서 빠짐"]
|
|
written = json.loads(
|
|
(tmp_path / "e" / cp.STABILITY_SOURCE_DIR / cp.MANIFEST_NAME).read_text("utf-8")
|
|
)
|
|
assert written["missing_cross_chainages"] == [35.5]
|