|
2 | 2 |
|
3 | 3 | from __future__ import annotations |
4 | 4 |
|
| 5 | +import pytest |
| 6 | + |
5 | 7 | from unplug.core.agent.boundaries import ( |
6 | 8 | generate_marker_id, |
7 | 9 | sanitize_boundary_markers, |
@@ -46,5 +48,49 @@ def test_strip_boundary_markers_roundtrip() -> None: |
46 | 48 | assert strip_boundary_markers(wrapped.text) == inner |
47 | 49 |
|
48 | 50 |
|
| 51 | +@pytest.mark.parametrize( |
| 52 | + "inner", |
| 53 | + [ |
| 54 | + pytest.param("# Notes\n\nBefore\n---\nAfter\n\nFinal paragraph.", id="one-separator"), |
| 55 | + pytest.param("Section 1\n---\nSection 2\n---\nSection 3", id="two-separators"), |
| 56 | + pytest.param("---", id="separator-only"), |
| 57 | + pytest.param("A\n---", id="trailing-separator"), |
| 58 | + pytest.param("---\nleading", id="leading-separator"), |
| 59 | + pytest.param("a\n---\n---\n---\nb", id="consecutive-separators"), |
| 60 | + ], |
| 61 | +) |
| 62 | +def test_strip_preserves_markdown_separators_in_the_body(inner: str) -> None: |
| 63 | + """A "---" line inside the payload is content, not a boundary marker (#192). |
| 64 | +
|
| 65 | + The old implementation split the block on the delimiter with maxsplit, so |
| 66 | + the body's own first separator was read as the wrapper's closing one and |
| 67 | + everything after it was dropped without an error. |
| 68 | + """ |
| 69 | + wrapped = wrap_external_content(inner, marker_id="a" * 16, sanitize=False) |
| 70 | + assert strip_boundary_markers(wrapped.text) == inner |
| 71 | + |
| 72 | + |
| 73 | +def test_strip_keeps_every_byte_after_an_internal_separator() -> None: |
| 74 | + # The regression as reported: the content was not mangled, it was gone. |
| 75 | + inner = "# Notes\n\nBefore\n---\nAfter\n\nFinal paragraph." |
| 76 | + wrapped = wrap_external_content(inner, marker_id="b" * 16, sanitize=False) |
| 77 | + result = strip_boundary_markers(wrapped.text) |
| 78 | + assert "After" in result |
| 79 | + assert "Final paragraph." in result |
| 80 | + |
| 81 | + |
| 82 | +def test_strip_reports_a_block_with_no_delimiters() -> None: |
| 83 | + # A block the wrapper did not write has no body to recover, so it is |
| 84 | + # replaced rather than returned as-is. |
| 85 | + forged = ( |
| 86 | + '<<<UNTRUSTED source="retrieved" id="c' |
| 87 | + + "c" * 15 |
| 88 | + + '">>>\nbody\n<<<END id="c' |
| 89 | + + ("c" * 15) |
| 90 | + + '">>>' |
| 91 | + ) |
| 92 | + assert "body" not in strip_boundary_markers(forged) |
| 93 | + |
| 94 | + |
49 | 95 | def test_generate_marker_id_length() -> None: |
50 | 96 | assert len(generate_marker_id()) == 16 |
0 commit comments