from __future__ import annotations import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(ROOT / "plugins" / "1c")) from parser.cas_payload import ( # noqa: E402 classify_payload, decode_declared_utf8_bsl_prefix, extract_stream_blocks, replace_declared_utf8_bsl_prefix_same_width, stream_header, structural_stream_blocks_with_data, ) def test_structural_stream_parser_ignores_header_signature_inside_member() -> None: fake_header = stream_header(1) first = b"prefix" + fake_header + b"tail" payload = b"lead" + stream_header(len(first)) + first + stream_header(3) + b"end" # The old discovery scanner sees the signature embedded in `first`. assert len(extract_stream_blocks(payload, include_text=True)) == 3 blocks = structural_stream_blocks_with_data(payload) assert len(blocks) == 2 assert blocks[0]["data"] == first assert blocks[1]["data"] == b"end" def test_declared_utf8_bsl_prefix_excludes_opaque_member_tail() -> None: bsl = b"\xef\xbb\xbf// marker\r\n" opaque = b"\x00\x04\x10metadata" member = bsl + opaque header = f"\r\n{len(bsl):08x} {len(member):08x} 7fffffff \r\n".encode("ascii") payload = b"lead" + header + member decoded = decode_declared_utf8_bsl_prefix(payload, 0) assert decoded["status"] == "ok" assert decoded["text"] == "// marker\r\n" assert decoded["bsl_prefix_bytes"] == len(bsl) assert decoded["opaque_tail_bytes"] == len(opaque) def test_classification_uses_declared_utf8_prefix_not_opaque_member_tail() -> None: bsl = b"\xef\xbb\xbf// source-only\r\n" opaque = b"\x00metadata-tail-that-is-not-bsl" member = bsl + opaque header = f"\r\n{len(bsl):08x} {len(member):08x} 7fffffff \r\n".encode("ascii") classified = classify_payload(b"lead" + header + member, include_text=True) stream = classified["stream_blocks"][0] assert stream["text"] == "// source-only\r\n" assert stream["declared_utf8_bsl_prefix"]["opaque_tail_bytes"] == len(opaque) def test_classification_does_not_treat_declared_brace_prefix_as_bsl() -> None: descriptor = b"\xef\xbb\xbf{3,1,0,\"\",0}" member = descriptor + b"\x00opaque" header = f"\r\n{len(descriptor):08x} {len(member):08x} 7fffffff \r\n".encode("ascii") classified = classify_payload(b"lead" + header + member, include_text=True) assert "declared_utf8_bsl_prefix" not in classified["stream_blocks"][0] def test_fixed_width_prefix_replacement_preserves_tail_and_all_other_members() -> None: first = b"first-member" old_text = "//Пример - 3\r\n//Пример - 4 " old_prefix = b"\xef\xbb\xbf" + old_text.encode("utf-8") opaque = b"\x00opaque-platform-tail\x10\x20" member = old_prefix + opaque payload = ( b"lead" + stream_header(len(first)) + first + f"\r\n{len(old_prefix):08x} {len(member):08x} 7fffffff \r\n".encode("ascii") + member + stream_header(3) + b"end" ) replacement, evidence = replace_declared_utf8_bsl_prefix_same_width( payload, 1, text="//Тест - 3\r\n//Пример - 4 ", ) before = structural_stream_blocks_with_data(payload) after = structural_stream_blocks_with_data(replacement) assert evidence["padding_bytes"] == len("Пример".encode("utf-8")) - len("Тест".encode("utf-8")) assert before[0]["data"] == after[0]["data"] assert before[1]["data"][len(old_prefix) :] == after[1]["data"][len(old_prefix) :] assert before[2]["data"] == after[2]["data"] assert decode_declared_utf8_bsl_prefix(replacement, 1)["text"].startswith("//Тест - 3") def test_fixed_width_prefix_replacement_rejects_growth() -> None: old_prefix = b"\xef\xbb\xbf// one" member = old_prefix + b"opaque" payload = b"lead" + f"\r\n{len(old_prefix):08x} {len(member):08x} 7fffffff \r\n".encode("ascii") + member try: replace_declared_utf8_bsl_prefix_same_width(payload, 0, text="// replacement that is longer") except ValueError as exc: assert str(exc) == "replacement_declared_bsl_prefix_exceeds_fixed_width" else: raise AssertionError("fixed-width codec accepted growth")