demo seed change
This commit is contained in:
111
scripts/test/demo_determinism.py
Normal file
111
scripts/test/demo_determinism.py
Normal file
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test deterministic cloning by creating multiple sessions and comparing data hashes.
|
||||
"""
|
||||
import asyncio
|
||||
import hashlib
|
||||
import json
|
||||
from typing import List, Dict
|
||||
import httpx
|
||||
|
||||
DEMO_API_URL = "http://localhost:8018"
|
||||
INTERNAL_API_KEY = "test-internal-key"
|
||||
|
||||
async def create_demo_session(tier: str = "professional") -> dict:
|
||||
"""Create a demo session"""
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.post(
|
||||
f"{DEMO_API_URL}/api/demo/sessions",
|
||||
json={"demo_account_type": tier}
|
||||
)
|
||||
return response.json()
|
||||
|
||||
async def get_all_data_from_service(
|
||||
service_url: str,
|
||||
tenant_id: str
|
||||
) -> dict:
|
||||
"""Fetch all data for a tenant from a service"""
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.get(
|
||||
f"{service_url}/internal/demo/export/{tenant_id}",
|
||||
headers={"X-Internal-API-Key": INTERNAL_API_KEY}
|
||||
)
|
||||
return response.json()
|
||||
|
||||
def calculate_data_hash(data: dict) -> str:
|
||||
"""
|
||||
Calculate SHA-256 hash of data, excluding audit timestamps.
|
||||
"""
|
||||
# Remove non-deterministic fields
|
||||
clean_data = remove_audit_fields(data)
|
||||
|
||||
# Sort keys for consistency
|
||||
json_str = json.dumps(clean_data, sort_keys=True)
|
||||
|
||||
return hashlib.sha256(json_str.encode()).hexdigest()
|
||||
|
||||
def remove_audit_fields(data: dict) -> dict:
|
||||
"""Remove created_at, updated_at fields recursively"""
|
||||
if isinstance(data, dict):
|
||||
return {
|
||||
k: remove_audit_fields(v)
|
||||
for k, v in data.items()
|
||||
if k not in ["created_at", "updated_at", "id"] # IDs are UUIDs
|
||||
}
|
||||
elif isinstance(data, list):
|
||||
return [remove_audit_fields(item) for item in data]
|
||||
else:
|
||||
return data
|
||||
|
||||
async def test_determinism(tier: str = "professional", iterations: int = 10):
|
||||
"""
|
||||
Test that cloning is deterministic across multiple sessions.
|
||||
"""
|
||||
print(f"Testing determinism for {tier} tier ({iterations} iterations)...")
|
||||
|
||||
services = [
|
||||
("inventory", "http://inventory-service:8002"),
|
||||
("production", "http://production-service:8003"),
|
||||
("recipes", "http://recipes-service:8004"),
|
||||
]
|
||||
|
||||
hashes_by_service = {svc[0]: [] for svc in services}
|
||||
|
||||
for i in range(iterations):
|
||||
# Create session
|
||||
session = await create_demo_session(tier)
|
||||
tenant_id = session["virtual_tenant_id"]
|
||||
|
||||
# Get data from each service
|
||||
for service_name, service_url in services:
|
||||
data = await get_all_data_from_service(service_url, tenant_id)
|
||||
data_hash = calculate_data_hash(data)
|
||||
hashes_by_service[service_name].append(data_hash)
|
||||
|
||||
# Cleanup
|
||||
async with httpx.AsyncClient() as client:
|
||||
await client.delete(f"{DEMO_API_URL}/api/demo/sessions/{session['session_id']}")
|
||||
|
||||
if (i + 1) % 10 == 0:
|
||||
print(f" Completed {i + 1}/{iterations} iterations")
|
||||
|
||||
# Check consistency
|
||||
all_consistent = True
|
||||
for service_name, hashes in hashes_by_service.items():
|
||||
unique_hashes = set(hashes)
|
||||
if len(unique_hashes) == 1:
|
||||
print(f"✅ {service_name}: All {iterations} hashes identical")
|
||||
else:
|
||||
print(f"❌ {service_name}: {len(unique_hashes)} different hashes found!")
|
||||
all_consistent = False
|
||||
|
||||
if all_consistent:
|
||||
print("\n✅ DETERMINISM TEST PASSED")
|
||||
return 0
|
||||
else:
|
||||
print("\n❌ DETERMINISM TEST FAILED")
|
||||
return 1
|
||||
|
||||
if __name__ == "__main__":
|
||||
exit_code = asyncio.run(test_determinism())
|
||||
exit(exit_code)
|
||||
Reference in New Issue
Block a user