"""342-3 세부 유역 저장본(부록 4 R15) — 열쇠가 같으면 다시 나누지 않음. - 열쇠 = 관 목록 · 노선(평면 · 종단 Z) · 분석 산출물 · 강우표 · 구조물 정의 자국. - 같은 열쇠 = _build 안 부름 · 관 목록은 사본 · 무엇이든 바뀌면 다시 셈. - [저장] 뒤 파일 한 벌 — 서버를 다시 켜도(메모리 비움) GET 열쇠로 읽힘. """ import os from pathlib import Path from types import SimpleNamespace import pytest from B04_PreProcess import B04_PreProcess_Router_Basins as basins from common_util.common_util_drainage_context import DrainageContext from common_util.common_util_drainage_detail import DrainageDetail from common_util.common_util_drainage_pipes import PipePoint from common_util.common_util_route_geometry import RouteVertex @pytest.fixture def setup(tmp_path, monkeypatch): monkeypatch.setattr(basins, "drainage_dir", lambda stored: tmp_path) basins._DETAIL_CACHE.clear() calls = SimpleNamespace(count=0) def build(stored_path, context, points): calls.count += 1 chainages = [p.chainage_m for p in points] if points else [50.0] return DrainageDetail(), [PipePoint(chainage_m=c, source="stream") for c in chainages] monkeypatch.setattr(basins, "_build", build) (tmp_path / "03_road_routing.npz").write_bytes(b"grid") context = DrainageContext( stored_path="x", project_root=Path("."), vertices=[RouteVertex(0.0, 0.0, 100.0, 0.0), RouteVertex(300.0, 0.0, 90.0, 300.0)], ) return tmp_path, context, calls def test_same_key_reuses_and_copies(setup): _, context, calls = setup points = [PipePoint(chainage_m=120.0, source="user")] _, first = basins._build_cached(context, points) first[0].x = 999.0 # 저장이 좌표를 채워도 저장본은 그대로 _, second = basins._build_cached(context, points) assert calls.count == 1 assert second[0].x is None def test_any_input_change_recomputes(setup): tmp_path, context, calls = setup points = [PipePoint(chainage_m=120.0, source="user")] basins._build_cached(context, points) basins._build_cached(context, [PipePoint(chainage_m=121.0, source="user")]) # 관 자리 context.vertices[1].z = 91.0 # 계획고(종단 Z) → 관 깊이 basins._build_cached(context, points) routing = tmp_path / "03_road_routing.npz" routing.write_bytes(b"grid-2") # 분석 다시 돎 os.utime(routing, ns=(1, 1)) basins._build_cached(context, points) assert calls.count == 4 def test_saved_file_survives_restart(setup): tmp_path, context, calls = setup stored = [PipePoint(chainage_m=120.0, source="stream")] detail, carried = basins._build(context.stored_path, context, stored) basins._save_detail_cache(context, stored, detail, carried) assert (tmp_path / basins.DETAIL_CACHE_FILENAME).exists() basins._DETAIL_CACHE.clear() # 서버 다시 켬 _, again = basins._build_cached(context, stored) assert calls.count == 1 assert [p.chainage_m for p in again] == [120.0]