|
14 | 14 | Table 전용 검증은 ``test_ir_tables.py``. |
15 | 15 | """ |
16 | 16 |
|
| 17 | +from pathlib import Path |
| 18 | + |
17 | 19 | import pytest |
18 | 20 | import rhwp |
19 | 21 | from pydantic import ValidationError |
20 | | -from rhwp.ir.nodes import HwpDocument, ParagraphBlock, TableBlock |
| 22 | +from rhwp.ir.nodes import DocumentSource, HwpDocument, ParagraphBlock, TableBlock |
21 | 23 |
|
22 | 24 | # * 반환 타입 / 캐시 |
23 | 25 |
|
@@ -205,3 +207,53 @@ def test_metadata_fields_are_none(parsed_hwp: rhwp.Document): |
205 | 207 | assert md.author is None |
206 | 208 | assert md.creation_time is None |
207 | 209 | assert md.modification_time is None |
| 210 | + |
| 211 | + |
| 212 | +# * source — rhwp.parse(path) 경로는 uri 에 원본 경로를 기록한다 |
| 213 | + |
| 214 | + |
| 215 | +def test_source_uri_matches_parse_path(parsed_hwp: rhwp.Document, hwp_sample: Path): |
| 216 | + """rhwp.parse(str(path)) 경로는 `HwpDocument.source.uri == str(path)` 를 보장한다. |
| 217 | +
|
| 218 | + RAG 응답 역추적 경로. normalize 는 수행하지 않는다 — 소비자 책임. |
| 219 | + """ |
| 220 | + ir = parsed_hwp.to_ir() |
| 221 | + assert isinstance(ir.source, DocumentSource) |
| 222 | + assert ir.source.uri == str(hwp_sample) |
| 223 | + |
| 224 | + |
| 225 | +def test_source_uri_matches_parse_path_hwpx(parsed_hwpx: rhwp.Document, hwpx_sample: Path): |
| 226 | + """HWPX 경로도 동일 계약.""" |
| 227 | + ir = parsed_hwpx.to_ir() |
| 228 | + assert isinstance(ir.source, DocumentSource) |
| 229 | + assert ir.source.uri == str(hwpx_sample) |
| 230 | + |
| 231 | + |
| 232 | +def test_document_source_uri_property(parsed_hwp: rhwp.Document, hwp_sample: Path): |
| 233 | + """``Document.source_uri`` getter 는 IR 생성 없이도 출처를 조회할 수 있어야 한다.""" |
| 234 | + assert parsed_hwp.source_uri == str(hwp_sample) |
| 235 | + |
| 236 | + |
| 237 | +def test_hwp_document_direct_construction_allows_null_source(): |
| 238 | + """Python 소비자가 IR 을 직접 구성하는 경로 (loader 등) — source=None 허용.""" |
| 239 | + ir = HwpDocument() |
| 240 | + assert ir.source is None |
| 241 | + assert ir.schema_name == "HwpDocument" |
| 242 | + assert ir.schema_version == "1.0" |
| 243 | + |
| 244 | + |
| 245 | +def test_hwp_document_json_null_source_roundtrip(): |
| 246 | + """source=None 상태의 JSON 도 Pydantic 재파싱 가능 — forward-compat 경로.""" |
| 247 | + import json |
| 248 | + |
| 249 | + original = HwpDocument() |
| 250 | + dumped = original.model_dump_json() |
| 251 | + parsed = HwpDocument.model_validate(json.loads(dumped)) |
| 252 | + assert parsed.source is None |
| 253 | + |
| 254 | + |
| 255 | +def test_document_source_is_frozen(): |
| 256 | + """``DocumentSource`` 는 ``frozen=True`` — 재할당은 ValidationError 로 거부.""" |
| 257 | + src = DocumentSource(uri="file:///tmp/example.hwp") |
| 258 | + with pytest.raises(ValidationError): |
| 259 | + src.uri = "file:///tmp/other.hwp" # type: ignore[misc] |
0 commit comments