mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-11-12 14:00:35 +00:00
test(utils): cover goal-objective and bash-exit input boundaries (#8048)
* test(utils): cover goal-objective and bash-exit input boundaries * test(utils): make the string-comparison boundary case actually pin the contract Review follow-up: 400 digits is below CPython's default int-max-str-digits cap (4300), so an implementation regressed to int(match.group(2)) would still pass. Derive the digit count from sys.get_int_max_str_digits() + 1 instead. Also document how this file differs from test_tool_result_meta.py (direct return contract vs message normalization). No production code changes. --------- Co-authored-by: jack12178 <jack12178@users.noreply.github.com>
This commit is contained in:
parent
d9b2cb4bcb
commit
4d95bff550
51
backend/tests/test_utils_bash_exit_boundaries.py
Normal file
51
backend/tests/test_utils_bash_exit_boundaries.py
Normal file
@ -0,0 +1,51 @@
|
||||
"""Boundary coverage for ``deerflow.utils.bash_exit``.
|
||||
|
||||
``backend/tests/test_tool_result_meta.py`` already drives the same markers
|
||||
through ``normalize_tool_message``. This file pins the direct return contract
|
||||
of ``bash_exit_status`` -- the exact ``(status, marker)`` tuple -- for the
|
||||
inputs where string handling, sign, or unbounded length matters. The few cases
|
||||
that overlap the existing suite are kept as the baseline for those assertions.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
from deerflow.utils.bash_exit import bash_exit_status
|
||||
|
||||
|
||||
def test_exit_code_tail_is_recognised_only_at_the_end() -> None:
|
||||
assert bash_exit_status("output\nExit Code: 0") == ("success", "Exit Code: 0")
|
||||
assert bash_exit_status("output\nExit Code: 1") == ("error", "Exit Code: 1")
|
||||
|
||||
|
||||
def test_embedded_phrase_in_ordinary_output_is_not_a_marker() -> None:
|
||||
assert bash_exit_status("he said Exit Code: 0 then left") is None
|
||||
|
||||
|
||||
def test_signed_zero_is_success() -> None:
|
||||
assert bash_exit_status("Command exited with code -0") == (
|
||||
"success",
|
||||
"Command exited with code -0",
|
||||
)
|
||||
|
||||
|
||||
def test_negative_and_timeout_codes_are_errors() -> None:
|
||||
for code in ("-1", "124", "137"):
|
||||
assert bash_exit_status(f"Exit Code: {code}") == ("error", f"Exit Code: {code}")
|
||||
|
||||
|
||||
def test_unbounded_digits_are_compared_as_strings() -> None:
|
||||
# CPython >= 3.11 refuses int() on digit strings longer than
|
||||
# sys.get_int_max_str_digits() (4300 by default). Exceeding that cap makes
|
||||
# an implementation regressed to int(match.group(2)) raise ValueError here
|
||||
# instead of silently returning the same ("error", marker) tuple.
|
||||
# A disabled cap (0) falls back to the default so the test still uses a
|
||||
# length far beyond the standard conversion limit.
|
||||
limit = sys.get_int_max_str_digits() or 4300
|
||||
huge = "9" * (limit + 1)
|
||||
assert bash_exit_status(f"Exit Code: {huge}") == ("error", f"Exit Code: {huge}")
|
||||
|
||||
|
||||
def test_trailing_whitespace_after_tail_is_allowed() -> None:
|
||||
assert bash_exit_status("done\nExit Code: 0 \n") == ("success", "Exit Code: 0")
|
||||
32
backend/tests/test_utils_goal_objective_boundaries.py
Normal file
32
backend/tests/test_utils_goal_objective_boundaries.py
Normal file
@ -0,0 +1,32 @@
|
||||
"""Boundary coverage for ``deerflow.utils.goal_objective``."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from deerflow.utils.goal_objective import MAX_GOAL_OBJECTIVE_CHARS, normalize_goal_objective
|
||||
|
||||
|
||||
def test_normalize_goal_objective_collapses_all_whitespace() -> None:
|
||||
assert normalize_goal_objective(" a \n\t b c ") == "a b c"
|
||||
|
||||
|
||||
def test_normalize_goal_objective_rejects_blank_only_input() -> None:
|
||||
for blank in ("", " ", "\n\t\r "):
|
||||
with pytest.raises(ValueError, match="must not be empty"):
|
||||
normalize_goal_objective(blank)
|
||||
|
||||
|
||||
def test_normalize_goal_objective_accepts_exact_limit() -> None:
|
||||
text = "x" * MAX_GOAL_OBJECTIVE_CHARS
|
||||
assert normalize_goal_objective(text) == text
|
||||
|
||||
|
||||
def test_normalize_goal_objective_rejects_one_over_limit() -> None:
|
||||
with pytest.raises(ValueError, match="at most"):
|
||||
normalize_goal_objective("x" * (MAX_GOAL_OBJECTIVE_CHARS + 1))
|
||||
|
||||
|
||||
def test_normalize_goal_objective_counts_characters_not_bytes() -> None:
|
||||
text = "\u4e2d" * MAX_GOAL_OBJECTIVE_CHARS
|
||||
assert normalize_goal_objective(text) == text
|
||||
Loading…
x
Reference in New Issue
Block a user