""" Test script demonstrating Redis caching in Dice Roll and Fibonacci APIs """ import requests import time BASE_URL = "http://localhost:8000" def print_header(title): print("\n" + "=" * 70) print(f" {title}") print("=" * 70) def print_section(title): print(f"\n{title}") print("-" * 70) def test_dice_with_caching(): """Test dice roll API with Redis caching""" print_header("DICE ROLL API - Redis Caching Test") session_id = "player_123" # First roll - should generate fresh results and cache them print_section("1️⃣ First Roll (Fresh - should cache)") response = requests.get(f"{BASE_URL}/api/dice/roll", params={ "session_id": session_id, "use_cache": True }) data1 = response.json() print(f" Session ID: {data1['session_id']}") print(f" Total Rolls: {data1['total']}") print(f" Statistics: {data1['statistics']}") print(f" Source: {data1['source']}") print(f" Cache Key: {data1['cache_key']}") print(f" Status: {response.status_code}") # Second roll - should return cached results (same rolls) print_section("2️⃣ Second Roll (Same Session - should hit cache)") response = requests.get(f"{BASE_URL}/api/dice/roll", params={ "session_id": session_id, "use_cache": True }) data2 = response.json() print(f" Source: {data2['source']}") print(f" Total Rolls: {data2['total']}") print(f" Statistics: {data2['statistics']}") print(f" Same results as first roll: {data1['dice_rolls'] == data2['dice_rolls']}") print(f" Status: {response.status_code}") # Third roll - different session, fresh results print_section("3️⃣ Third Roll (Different Session - fresh)") response = requests.get(f"{BASE_URL}/api/dice/roll", params={ "session_id": "player_456", "use_cache": True }) data3 = response.json() print(f" Session ID: {data3['session_id']}") print(f" Source: {data3['source']}") print(f" Total Rolls: {data3['total']}") print(f" Statistics: {data3['statistics']}") print(f" Status: {response.status_code}") # Fourth roll - cache disabled print_section("4️⃣ Fourth Roll (Cache Disabled)") response = requests.get(f"{BASE_URL}/api/dice/roll", params={ "session_id": session_id, "use_cache": False }) data4 = response.json() print(f" Source: {data4['source']}") print(f" Statistics: {data4['statistics']}") print(f" Different from cached: {data1['dice_rolls'] != data4['dice_rolls']}") print(f" Status: {response.status_code}") def test_fibonacci_with_caching(): """Test Fibonacci API with Redis caching""" print_header("FIBONACCI API - Redis Caching Test") # Test with n=10 n = 10 # First request - should compute and cache print_section(f"1️⃣ First Request (n={n}) - Fresh Computation") start = time.time() response = requests.post(f"{BASE_URL}/api/tasks/fibonacci", params={ "n": n, "use_cache": True }) elapsed1 = time.time() - start data1 = response.json() print(f" n: {data1['n']}") print(f" Status: {data1['status']}") print(f" Source: {data1['source']}") print(f" Response Time: {elapsed1:.3f}s") print(f" Cache Key: {data1['cache_key']}") if data1['source'] == 'celery_task': print(f" Task ID: {data1['task_id']}") print(f" Check result at: {data1['check_result_at']}") # Wait for task completion print("\n ⏳ Waiting for task to complete...") time.sleep(2) # Get result task_response = requests.get(f"{BASE_URL}/api/tasks/{data1['task_id']}") task_data = task_response.json() print(f" ✅ Task Status: {task_data['status']}") if task_data['status'] == 'completed': result = task_data['result'] print(f" Result: Fibonacci({n}) = {result.get('result', result.get('fibonacci'))}") print(f" Computation Time: {result.get('computation_time_seconds', 'N/A')}s") else: print(f" ✅ Result: Fibonacci({n}) = {data1['result']}") # Second request - should hit cache immediately print_section(f"2️⃣ Second Request (n={n}) - Should Hit Cache") start = time.time() response = requests.post(f"{BASE_URL}/api/tasks/fibonacci", params={ "n": n, "use_cache": True }) elapsed2 = time.time() - start data2 = response.json() print(f" Status: {data2['status']}") print(f" Source: {data2['source']}") print(f" Response Time: {elapsed2:.3f}s") print(f" Result: Fibonacci({n}) = {data2.get('result', 'N/A')}") print(f" 🚀 Speedup: {elapsed1/elapsed2:.1f}x faster!") # Third request - cache disabled, force recomputation print_section(f"3️⃣ Third Request (n={n}) - Cache Disabled") start = time.time() response = requests.post(f"{BASE_URL}/api/tasks/fibonacci", params={ "n": n, "use_cache": False }) elapsed3 = time.time() - start data3 = response.json() print(f" Status: {data3['status']}") print(f" Source: {data3['source']}") print(f" Response Time: {elapsed3:.3f}s") # Test with larger number n_large = 20 print_section(f"4️⃣ Large Fibonacci (n={n_large}) - First Request") start = time.time() response = requests.post(f"{BASE_URL}/api/tasks/fibonacci", params={ "n": n_large, "use_cache": True }) elapsed_large1 = time.time() - start data_large = response.json() print(f" Source: {data_large['source']}") print(f" Response Time: {elapsed_large1:.3f}s") if data_large['source'] == 'celery_task': print(f" Task ID: {data_large['task_id']}") print("\n ⏳ Waiting for computation...") time.sleep(3) task_response = requests.get(f"{BASE_URL}/api/tasks/{data_large['task_id']}") task_data = task_response.json() if task_data['status'] == 'completed': result = task_data['result'] print(f" ✅ Result: Fibonacci({n_large}) = {result.get('result', result.get('fibonacci'))}") # Cached request for large number print_section(f"5️⃣ Large Fibonacci (n={n_large}) - Cached Request") start = time.time() response = requests.post(f"{BASE_URL}/api/tasks/fibonacci", params={ "n": n_large, "use_cache": True }) elapsed_large2 = time.time() - start data_large2 = response.json() print(f" Source: {data_large2['source']}") print(f" Response Time: {elapsed_large2:.3f}s") if data_large2['source'] == 'cache': print(f" ✅ Result: Fibonacci({n_large}) = {data_large2['result']}") print(f" 🚀 Much faster with cache!") def test_cache_stats(): """Display Redis cache statistics""" print_header("REDIS CACHE STATISTICS") response = requests.get(f"{BASE_URL}/api/cache/stats") data = response.json() stats = data['stats'] print(f"\n Memory Used: {stats['used_memory']}") print(f" Total Keys: {stats['total_keys']}") print(f" Connected Clients: {stats['connected_clients']}") print(f" Cache Hits: {stats['hits']}") print(f" Cache Misses: {stats['misses']}") print(f" Hit Ratio: {stats['hit_ratio_percent']}%") print(f" Uptime: {stats['uptime_seconds']} seconds") def main(): print("\n" + "🎲" * 35) print(" Redis Caching Test Suite for DevServer API") print("🎲" * 35) try: # Test Dice Roll API test_dice_with_caching() # Test Fibonacci API test_fibonacci_with_caching() # Display cache statistics test_cache_stats() print("\n" + "=" * 70) print(" ✅ All tests completed successfully!") print("=" * 70) print("\n💡 Key Takeaways:") print(" • Dice rolls are cached per session (5 min TTL)") print(" • Fibonacci results are cached globally (1 hour TTL)") print(" • Cache dramatically improves response times") print(" • Both APIs support cache bypass with use_cache=false") print("\n") except Exception as e: print(f"\n❌ Error: {e}") if __name__ == "__main__": main()