"""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"}, )