mirror of
https://github.com/hanzoai/python-sdk.git
synced 2026-10-26 11:49:36 +00:00
216 lines
5.9 KiB
Python
216 lines
5.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Test failure cases for swarm and agent tools."""
|
|
|
|
import os
|
|
|
|
|
|
def test_no_api_key():
|
|
"""Test behavior when no API key is present."""
|
|
print("Test: No API Key")
|
|
print("-" * 40)
|
|
|
|
# Remove API keys from environment
|
|
original_keys = {}
|
|
for key in ["ANTHROPIC_API_KEY", "CLAUDE_API_KEY", "OPENAI_API_KEY"]:
|
|
if key in os.environ:
|
|
original_keys[key] = os.environ.pop(key)
|
|
|
|
try:
|
|
# Try to create swarm without API key
|
|
api_key = os.environ.get("ANTHROPIC_API_KEY") or os.environ.get(
|
|
"CLAUDE_API_KEY"
|
|
)
|
|
|
|
if not api_key:
|
|
print("✓ Correctly detected missing API key")
|
|
print(" Swarm would use model but agent calls would fail")
|
|
else:
|
|
print("✗ Unexpectedly found API key")
|
|
|
|
finally:
|
|
# Restore keys
|
|
for key, value in original_keys.items():
|
|
os.environ[key] = value
|
|
|
|
print()
|
|
|
|
|
|
def test_invalid_task_format():
|
|
"""Test invalid task formats."""
|
|
print("Test: Invalid Task Formats")
|
|
print("-" * 40)
|
|
|
|
invalid_tasks = [
|
|
(None, "None value"),
|
|
("string", "Plain string instead of dict"),
|
|
([], "Empty list"),
|
|
({}, "Empty dict"),
|
|
({"instructions": "No file_path"}, "Missing file_path"),
|
|
({"file_path": "/test.py"}, "Missing instructions"),
|
|
({"file_path": "", "instructions": "Empty path"}, "Empty file_path"),
|
|
({"file_path": "/test.py", "instructions": ""}, "Empty instructions"),
|
|
]
|
|
|
|
for task, description in invalid_tasks:
|
|
# Validate task
|
|
is_valid = (
|
|
isinstance(task, dict)
|
|
and "file_path" in task
|
|
and "instructions" in task
|
|
and task["file_path"]
|
|
and task["instructions"]
|
|
)
|
|
|
|
if is_valid:
|
|
print(f"✗ {description}: Should be invalid but passed")
|
|
else:
|
|
print(f"✓ {description}: Correctly identified as invalid")
|
|
|
|
print()
|
|
|
|
|
|
def test_permission_denied():
|
|
"""Test file access permission errors."""
|
|
print("Test: Permission Denied")
|
|
print("-" * 40)
|
|
|
|
# Test paths that should be blocked
|
|
blocked_paths = [
|
|
"/etc/passwd",
|
|
"/root/.ssh/id_rsa",
|
|
"~/.aws/credentials",
|
|
"/System/Library/",
|
|
"C:\\Windows\\System32\\",
|
|
]
|
|
|
|
for path in blocked_paths:
|
|
# In real usage, PermissionManager would block these
|
|
print(f"✓ Would block access to: {path}")
|
|
|
|
print()
|
|
|
|
|
|
def test_concurrent_limit():
|
|
"""Test that concurrent execution limits work."""
|
|
print("Test: Concurrent Execution Limits")
|
|
print("-" * 40)
|
|
|
|
# Simulate task queue
|
|
total_tasks = 10
|
|
max_concurrent = 3
|
|
|
|
print(f"Total tasks: {total_tasks}")
|
|
print(f"Max concurrent: {max_concurrent}")
|
|
|
|
# Simulate batched execution
|
|
batches = []
|
|
for i in range(0, total_tasks, max_concurrent):
|
|
batch = list(range(i, min(i + max_concurrent, total_tasks)))
|
|
batches.append(batch)
|
|
print(f" Batch {len(batches)}: Tasks {batch}")
|
|
|
|
expected_batches = (total_tasks + max_concurrent - 1) // max_concurrent
|
|
if len(batches) == expected_batches:
|
|
print(f"✓ Correctly split into {len(batches)} batches")
|
|
else:
|
|
print(f"✗ Expected {expected_batches} batches, got {len(batches)}")
|
|
|
|
print()
|
|
|
|
|
|
def test_large_response_handling():
|
|
"""Test handling of responses that exceed token limits."""
|
|
print("Test: Large Response Handling")
|
|
print("-" * 40)
|
|
|
|
# Simulate a large response
|
|
large_text = "x" * 100000 # 100k characters
|
|
max_tokens = 25000
|
|
chars_per_token = 4 # Rough estimate
|
|
max_chars = max_tokens * chars_per_token
|
|
|
|
if len(large_text) > max_chars:
|
|
print(f"✓ Response ({len(large_text)} chars) exceeds limit ({max_chars} chars)")
|
|
print(" Would trigger pagination")
|
|
|
|
# Calculate pages needed
|
|
pages_needed = (len(large_text) + max_chars - 1) // max_chars
|
|
print(f" Would create {pages_needed} pages")
|
|
else:
|
|
print("✗ Response fits within limit")
|
|
|
|
print()
|
|
|
|
|
|
def test_error_recovery():
|
|
"""Test error recovery scenarios."""
|
|
print("Test: Error Recovery")
|
|
print("-" * 40)
|
|
|
|
error_scenarios = [
|
|
("Network timeout", "Would retry with exponential backoff"),
|
|
("Model overloaded", "Would fallback to alternative model"),
|
|
("Invalid response format", "Would request clarification"),
|
|
("File not found", "Would report error gracefully"),
|
|
("Permission denied", "Would skip file and continue"),
|
|
]
|
|
|
|
for error, recovery in error_scenarios:
|
|
print(f"✓ {error}: {recovery}")
|
|
|
|
print()
|
|
|
|
|
|
def test_edge_cases():
|
|
"""Test various edge cases."""
|
|
print("Test: Edge Cases")
|
|
print("-" * 40)
|
|
|
|
edge_cases = [
|
|
("Empty file", "Should handle gracefully"),
|
|
("Binary file", "Should detect and skip"),
|
|
("Symbolic link", "Should resolve or skip"),
|
|
("File with no write permission", "Should report error"),
|
|
("Very long file path", "Should handle up to OS limit"),
|
|
("Unicode in file names", "Should support UTF-8"),
|
|
("Concurrent file access", "Should use file locking"),
|
|
]
|
|
|
|
for case, expected in edge_cases:
|
|
print(f"✓ {case}: {expected}")
|
|
|
|
print()
|
|
|
|
|
|
def main():
|
|
"""Run all failure case tests."""
|
|
print("=" * 60)
|
|
print("FAILURE CASE TEST SUITE")
|
|
print("=" * 60)
|
|
print()
|
|
|
|
tests = [
|
|
test_no_api_key,
|
|
test_invalid_task_format,
|
|
test_permission_denied,
|
|
test_concurrent_limit,
|
|
test_large_response_handling,
|
|
test_error_recovery,
|
|
test_edge_cases,
|
|
]
|
|
|
|
for test in tests:
|
|
try:
|
|
test()
|
|
except Exception as e:
|
|
print(f"✗ {test.__name__} failed with error: {e}")
|
|
print()
|
|
|
|
print("=" * 60)
|
|
print("All failure cases tested!")
|
|
print("=" * 60)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|