113 lines
4.2 KiB
Python
113 lines
4.2 KiB
Python
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")
|