"""Unit tests for docker_agent_sandbox.tools._utils — no Docker required.""" import pytest from docker_agent_sandbox.tools._utils import ( _MAX_OUTPUT_CHARS, _MAX_OUTPUT_LINES, _TRUNCATION_NOTICE, _parent, truncate_output, ) # --------------------------------------------------------------------------- # truncate_output # --------------------------------------------------------------------------- def test_truncate_output_short_string_unchanged(): assert truncate_output("hello world") == "hello world" def test_truncate_output_empty_string(): assert truncate_output("") == "" def test_truncate_output_exactly_at_line_limit(): output = "line\n" * _MAX_OUTPUT_LINES assert truncate_output(output) == output def test_truncate_output_one_over_line_limit(): output = "line\n" * (_MAX_OUTPUT_LINES + 1) result = truncate_output(output) assert _TRUNCATION_NOTICE in result # 200 "line\n" kept + notice; the 201st "line" must not appear assert result.count("line\n") == _MAX_OUTPUT_LINES def test_truncate_output_line_limit_keeps_first_200(): output = "line\n" * 250 result = truncate_output(output) assert result.startswith("line\n" * _MAX_OUTPUT_LINES) assert _TRUNCATION_NOTICE in result def test_truncate_output_exactly_at_char_limit(): output = "x" * _MAX_OUTPUT_CHARS assert truncate_output(output) == output def test_truncate_output_one_over_char_limit(): output = "x" * (_MAX_OUTPUT_CHARS + 1) result = truncate_output(output) assert _TRUNCATION_NOTICE in result # Exactly _MAX_OUTPUT_CHARS x's are kept before the notice assert result.startswith("x" * _MAX_OUTPUT_CHARS) assert result[_MAX_OUTPUT_CHARS] != "x" def test_truncate_output_char_limit_takes_first_20000(): output = "x" * 25_000 result = truncate_output(output) assert result.startswith("x" * _MAX_OUTPUT_CHARS) assert _TRUNCATION_NOTICE in result def test_truncate_output_line_limit_checked_before_char_limit(): # 201 lines of 200 chars each = 201 * 201 = ~40k chars (> char limit too). # Lines are checked first, so only the line-limit truncation notice appears. output = ("x" * 200 + "\n") * 201 result = truncate_output(output) assert _TRUNCATION_NOTICE in result # After line truncation the result is 200 * 201 = 40200 chars + notice, # which is still > _MAX_OUTPUT_CHARS, so the char truncation fires too. # Either way the result must be shorter than the input. assert len(result) < len(output) # --------------------------------------------------------------------------- # _parent # --------------------------------------------------------------------------- @pytest.mark.parametrize( "path, expected", [ ("/foo/bar/baz.txt", "/foo/bar"), ("/foo/bar/baz/", "/foo/bar"), # trailing slash stripped before dirname ("/foo/bar", "/foo"), ("/foo", "/"), ("foo/bar/baz", "foo/bar"), ("foo/bar", "foo"), ("foo", "."), ("", "."), ], ) def test_parent(path, expected): assert _parent(path) == expected