|
|
|
|
|
""" |
|
|
End-to-end test for LocalDockerProvider. |
|
|
|
|
|
This script tests the complete flow: |
|
|
1. Start a container using LocalDockerProvider |
|
|
2. Wait for it to be ready |
|
|
3. Make HTTP requests to test the environment |
|
|
4. Clean up the container |
|
|
""" |
|
|
|
|
|
import sys |
|
|
from pathlib import Path |
|
|
|
|
|
|
|
|
sys.path.insert(0, str(Path(__file__).parent.parent.parent)) |
|
|
|
|
|
import requests |
|
|
|
|
|
from core.containers.runtime import LocalDockerProvider |
|
|
|
|
|
|
|
|
def test_local_docker_provider(): |
|
|
"""Test LocalDockerProvider end-to-end.""" |
|
|
print("=" * 60) |
|
|
print("LocalDockerProvider End-to-End Test") |
|
|
print("=" * 60) |
|
|
print() |
|
|
|
|
|
provider = None |
|
|
|
|
|
try: |
|
|
|
|
|
print("Step 1: Creating LocalDockerProvider...") |
|
|
provider = LocalDockerProvider() |
|
|
print("β Provider created\n") |
|
|
|
|
|
|
|
|
print("Step 2: Starting echo-env container...") |
|
|
base_url = provider.start_container("echo-env:latest") |
|
|
print(f"β Container started at: {base_url}") |
|
|
if provider._container_id: |
|
|
print(f" Container ID: {provider._container_id[:12]}...") |
|
|
if provider._container_name: |
|
|
print(f" Container name: {provider._container_name}\n") |
|
|
|
|
|
|
|
|
print("Step 3: Waiting for container to be ready...") |
|
|
provider.wait_for_ready(base_url, timeout_s=30.0) |
|
|
print("β Container is ready!\n") |
|
|
|
|
|
|
|
|
print("Step 4: Testing /health endpoint...") |
|
|
response = requests.get(f"{base_url}/health") |
|
|
print(f" Status: {response.status_code}") |
|
|
print(f" Response: {response.json()}") |
|
|
assert response.status_code == 200 |
|
|
assert response.json()["status"] == "healthy" |
|
|
print("β Health check passed\n") |
|
|
|
|
|
|
|
|
print("Step 5: Testing /reset endpoint...") |
|
|
response = requests.post( |
|
|
f"{base_url}/reset", |
|
|
json={}, |
|
|
headers={"Content-Type": "application/json"}, |
|
|
) |
|
|
print(f" Status: {response.status_code}") |
|
|
data = response.json() |
|
|
print(f" Message: {data['observation']['echoed_message']}") |
|
|
print(f" Reward: {data['reward']}") |
|
|
print(f" Done: {data['done']}") |
|
|
assert response.status_code == 200 |
|
|
assert data["observation"]["echoed_message"] == "Echo environment ready!" |
|
|
print("β Reset test passed\n") |
|
|
|
|
|
|
|
|
print("Step 6: Testing /step endpoint...") |
|
|
response = requests.post( |
|
|
f"{base_url}/step", |
|
|
json={"action": {"message": "Hello from LocalDockerProvider!"}}, |
|
|
headers={"Content-Type": "application/json"}, |
|
|
) |
|
|
print(f" Status: {response.status_code}") |
|
|
data = response.json() |
|
|
print(f" Echoed: {data['observation']['echoed_message']}") |
|
|
print(f" Length: {data['observation']['message_length']}") |
|
|
print(f" Reward: {data['reward']}") |
|
|
assert response.status_code == 200 |
|
|
assert data["observation"]["echoed_message"] == "Hello from LocalDockerProvider!" |
|
|
assert data["observation"]["message_length"] == 31 |
|
|
print("β Step test passed\n") |
|
|
|
|
|
|
|
|
print("Step 7: Testing /state endpoint...") |
|
|
response = requests.get(f"{base_url}/state") |
|
|
print(f" Status: {response.status_code}") |
|
|
data = response.json() |
|
|
print(f" Episode ID: {data['episode_id']}") |
|
|
print(f" Step count: {data['step_count']}") |
|
|
assert response.status_code == 200 |
|
|
assert data["step_count"] == 1 |
|
|
print("β State test passed\n") |
|
|
|
|
|
|
|
|
print("Step 8: Testing multiple steps...") |
|
|
for i in range(3): |
|
|
response = requests.post( |
|
|
f"{base_url}/step", |
|
|
json={"action": {"message": f"Message {i+1}"}}, |
|
|
headers={"Content-Type": "application/json"}, |
|
|
) |
|
|
assert response.status_code == 200 |
|
|
print(f" Step {i+1}: β") |
|
|
|
|
|
|
|
|
response = requests.get(f"{base_url}/state") |
|
|
data = response.json() |
|
|
assert data["step_count"] == 4 |
|
|
print(f" Final step count: {data['step_count']}") |
|
|
print("β Multiple steps test passed\n") |
|
|
|
|
|
print("=" * 60) |
|
|
print("β All tests passed!") |
|
|
print("=" * 60) |
|
|
print() |
|
|
|
|
|
return True |
|
|
|
|
|
except Exception as e: |
|
|
print(f"\nβ Test failed: {e}") |
|
|
import traceback |
|
|
traceback.print_exc() |
|
|
return False |
|
|
|
|
|
finally: |
|
|
|
|
|
if provider is not None: |
|
|
print("\nStep 9: Cleaning up container...") |
|
|
try: |
|
|
provider.stop_container() |
|
|
print("β Container stopped and removed\n") |
|
|
except Exception as e: |
|
|
print(f"β οΈ Cleanup warning: {e}\n") |
|
|
|
|
|
|
|
|
def test_provider_with_custom_port(): |
|
|
"""Test provider with custom port.""" |
|
|
print("=" * 60) |
|
|
print("LocalDockerProvider with Custom Port Test") |
|
|
print("=" * 60) |
|
|
print() |
|
|
|
|
|
provider = None |
|
|
|
|
|
try: |
|
|
provider = LocalDockerProvider() |
|
|
|
|
|
print("Starting container on custom port 8123...") |
|
|
base_url = provider.start_container("echo-env:latest", port=8123) |
|
|
print(f"β Started at: {base_url}") |
|
|
assert ":8123" in base_url |
|
|
|
|
|
print("Waiting for ready...") |
|
|
provider.wait_for_ready(base_url) |
|
|
print("β Ready!") |
|
|
|
|
|
print("Testing health...") |
|
|
response = requests.get(f"{base_url}/health") |
|
|
assert response.status_code == 200 |
|
|
print("β Health check passed") |
|
|
|
|
|
print("\nβ Custom port test passed!\n") |
|
|
return True |
|
|
|
|
|
except Exception as e: |
|
|
print(f"\nβ Test failed: {e}") |
|
|
return False |
|
|
|
|
|
finally: |
|
|
if provider is not None: |
|
|
provider.stop_container() |
|
|
print("β Cleaned up\n") |
|
|
|
|
|
|
|
|
def test_provider_with_env_vars(): |
|
|
"""Test provider with environment variables.""" |
|
|
print("=" * 60) |
|
|
print("LocalDockerProvider with Environment Variables Test") |
|
|
print("=" * 60) |
|
|
print() |
|
|
|
|
|
provider = None |
|
|
|
|
|
try: |
|
|
provider = LocalDockerProvider() |
|
|
|
|
|
print("Starting container with environment variables...") |
|
|
base_url = provider.start_container( |
|
|
"echo-env:latest", |
|
|
env_vars={"DEBUG": "true", "LOG_LEVEL": "info"} |
|
|
) |
|
|
print(f"β Started at: {base_url}") |
|
|
|
|
|
print("Waiting for ready...") |
|
|
provider.wait_for_ready(base_url) |
|
|
print("β Ready!") |
|
|
|
|
|
print("Testing health...") |
|
|
response = requests.get(f"{base_url}/health") |
|
|
assert response.status_code == 200 |
|
|
print("β Health check passed") |
|
|
|
|
|
print("\nβ Environment variables test passed!\n") |
|
|
return True |
|
|
|
|
|
except Exception as e: |
|
|
print(f"\nβ Test failed: {e}") |
|
|
return False |
|
|
|
|
|
finally: |
|
|
if provider is not None: |
|
|
provider.stop_container() |
|
|
print("β Cleaned up\n") |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
print() |
|
|
print("π³ LocalDockerProvider Test Suite") |
|
|
print() |
|
|
|
|
|
results = [] |
|
|
|
|
|
|
|
|
results.append(("Basic End-to-End", test_local_docker_provider())) |
|
|
|
|
|
|
|
|
results.append(("Custom Port", test_provider_with_custom_port())) |
|
|
|
|
|
|
|
|
results.append(("Environment Variables", test_provider_with_env_vars())) |
|
|
|
|
|
|
|
|
print("=" * 60) |
|
|
print("Test Summary") |
|
|
print("=" * 60) |
|
|
for name, passed in results: |
|
|
status = "β PASSED" if passed else "β FAILED" |
|
|
print(f"{name:25} {status}") |
|
|
print("=" * 60) |
|
|
|
|
|
all_passed = all(result for _, result in results) |
|
|
if all_passed: |
|
|
print("\nπ All tests passed!") |
|
|
exit(0) |
|
|
else: |
|
|
print("\nβ Some tests failed") |
|
|
exit(1) |
|
|
|