216 lines
7.8 KiB
Python
216 lines
7.8 KiB
Python
"""Step definitions for inline tool executor coverage boost tests."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from behave import given, then, when
|
|
from behave.runner import Context
|
|
|
|
from cleveragents.skills.inline_executor import InlineToolExecutor
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Givens — Constructor validation
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("I create an inline executor with invalid max runtime")
|
|
def create_executor_invalid_runtime(context: Context) -> None:
|
|
"""Attempt to create executor with non-positive runtime."""
|
|
context.executor_error = None
|
|
try:
|
|
InlineToolExecutor(max_runtime_seconds=-1.0)
|
|
except ValueError as exc:
|
|
context.executor_error = exc
|
|
|
|
|
|
@given("I create an inline executor with invalid max output")
|
|
def create_executor_invalid_output(context: Context) -> None:
|
|
"""Attempt to create executor with non-positive max output."""
|
|
context.executor_error = None
|
|
try:
|
|
InlineToolExecutor(max_output_bytes=0)
|
|
except ValueError as exc:
|
|
context.executor_error = exc
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Then — Constructor validation assertions
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@then("creating the executor should raise a ValueError about runtime")
|
|
def assert_runtime_value_error(context: Context) -> None:
|
|
"""Assert ValueError was raised about runtime."""
|
|
assert context.executor_error is not None, "Expected ValueError"
|
|
assert "runtime" in str(context.executor_error).lower(), (
|
|
f"Expected 'runtime' in error: {context.executor_error}"
|
|
)
|
|
|
|
|
|
@then("creating the executor should raise a ValueError about output")
|
|
def assert_output_value_error(context: Context) -> None:
|
|
"""Assert ValueError was raised about output."""
|
|
assert context.executor_error is not None, "Expected ValueError"
|
|
assert "output" in str(context.executor_error).lower(), (
|
|
f"Expected 'output' in error: {context.executor_error}"
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Then — Property accessors
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@then("the executor max_runtime_seconds should be {expected:g}")
|
|
def assert_max_runtime(context: Context, expected: float) -> None:
|
|
"""Assert max_runtime_seconds property value."""
|
|
actual = context.inline_executor.max_runtime_seconds
|
|
assert actual == expected, f"Expected {expected}, got {actual}"
|
|
|
|
|
|
@then("the executor max_output_bytes should be {expected:d}")
|
|
def assert_max_output(context: Context, expected: int) -> None:
|
|
"""Assert max_output_bytes property value."""
|
|
actual = context.inline_executor.max_output_bytes
|
|
assert actual == expected, f"Expected {expected}, got {actual}"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# When — Null argument guards
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@when("I execute with None tool")
|
|
def execute_with_none_tool(context: Context) -> None:
|
|
"""Execute with None tool argument."""
|
|
context.exec_error = None
|
|
try:
|
|
context.inline_executor.execute(
|
|
tool=None, # type: ignore[arg-type]
|
|
context=context.inline_context,
|
|
input_data={},
|
|
)
|
|
except ValueError as exc:
|
|
context.exec_error = exc
|
|
|
|
|
|
@when("I execute with None context")
|
|
def execute_with_none_context(context: Context) -> None:
|
|
"""Execute with None context argument."""
|
|
context.exec_error = None
|
|
try:
|
|
context.inline_executor.execute(
|
|
tool=context.inline_tool,
|
|
context=None, # type: ignore[arg-type]
|
|
input_data={},
|
|
)
|
|
except ValueError as exc:
|
|
context.exec_error = exc
|
|
|
|
|
|
@when("I execute with None input_data")
|
|
def execute_with_none_input(context: Context) -> None:
|
|
"""Execute with None input_data argument."""
|
|
context.exec_error = None
|
|
try:
|
|
context.inline_executor.execute(
|
|
tool=context.inline_tool,
|
|
context=context.inline_context,
|
|
input_data=None, # type: ignore[arg-type]
|
|
)
|
|
except ValueError as exc:
|
|
context.exec_error = exc
|
|
|
|
|
|
@when("I validate with None tool")
|
|
def validate_with_none_tool(context: Context) -> None:
|
|
"""Validate with None tool argument."""
|
|
context.exec_error = None
|
|
try:
|
|
context.inline_executor.validate_tool(None) # type: ignore[arg-type]
|
|
except ValueError as exc:
|
|
context.exec_error = exc
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Then — Null argument guard assertions
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@then("executing should raise a ValueError about tool")
|
|
def assert_tool_value_error(context: Context) -> None:
|
|
"""Assert ValueError was raised about tool."""
|
|
assert context.exec_error is not None, "Expected ValueError"
|
|
assert "tool" in str(context.exec_error).lower(), (
|
|
f"Expected 'tool' in error: {context.exec_error}"
|
|
)
|
|
|
|
|
|
@then("executing should raise a ValueError about context")
|
|
def assert_context_value_error(context: Context) -> None:
|
|
"""Assert ValueError was raised about context."""
|
|
assert context.exec_error is not None, "Expected ValueError"
|
|
assert "context" in str(context.exec_error).lower(), (
|
|
f"Expected 'context' in error: {context.exec_error}"
|
|
)
|
|
|
|
|
|
@then("executing should raise a ValueError about input_data")
|
|
def assert_input_value_error(context: Context) -> None:
|
|
"""Assert ValueError was raised about input_data."""
|
|
assert context.exec_error is not None, "Expected ValueError"
|
|
assert "input_data" in str(context.exec_error).lower(), (
|
|
f"Expected 'input_data' in error: {context.exec_error}"
|
|
)
|
|
|
|
|
|
@then("validating should raise a ValueError about tool")
|
|
def assert_validate_tool_error(context: Context) -> None:
|
|
"""Assert ValueError was raised about tool during validation."""
|
|
assert context.exec_error is not None, "Expected ValueError"
|
|
assert "tool" in str(context.exec_error).lower(), (
|
|
f"Expected 'tool' in error: {context.exec_error}"
|
|
)
|
|
|
|
|
|
@then("the inline result duration should be zero")
|
|
def assert_zero_duration(context: Context) -> None:
|
|
"""Assert the result duration is zero (validation failure path)."""
|
|
assert context.inline_result.duration_ms == 0.0, (
|
|
f"Expected 0.0 duration, got {context.inline_result.duration_ms}"
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# When — Path validation
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@when("I execute the inline tool with path input escaping sandbox")
|
|
def execute_with_escaping_path(context: Context) -> None:
|
|
"""Execute with a path that escapes the sandbox."""
|
|
context.inline_result = context.inline_executor.execute(
|
|
tool=context.inline_tool,
|
|
context=context.inline_context,
|
|
input_data={"file_path": "/etc/passwd"},
|
|
)
|
|
|
|
|
|
@when("I execute the inline tool with path input inside sandbox")
|
|
def execute_with_valid_path(context: Context) -> None:
|
|
"""Execute with a path inside the sandbox."""
|
|
context.inline_result = context.inline_executor.execute(
|
|
tool=context.inline_tool,
|
|
context=context.inline_context,
|
|
input_data={"file_path": "/tmp/inline-sandbox/data.txt"},
|
|
)
|
|
|
|
|
|
@when("I execute the inline tool with an invalid path value")
|
|
def execute_with_invalid_path(context: Context) -> None:
|
|
"""Execute with a path value containing null bytes."""
|
|
context.inline_result = context.inline_executor.execute(
|
|
tool=context.inline_tool,
|
|
context=context.inline_context,
|
|
input_data={"file_path": "\x00invalid"},
|
|
)
|