| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- import asyncio
- import httpx
- import websockets
- import json
- import time
- import random
- BASE_URL = "http://localhost:8000"
- WS_URL = "ws://localhost:8000"
- async def simulate_user(user_id):
- """Simulates a single user behavior"""
- email = f"testuser_{user_id}@example.com"
- password = "password123"
-
- async with httpx.AsyncClient() as client:
- # 0. Try to register first (in case users don't exist)
- try:
- await client.post(f"{BASE_URL}/auth/register", json={
- "email": email,
- "password": password,
- "first_name": "Test",
- "last_name": "User",
- "phone": "123456"
- })
- except: pass
- # 1. Try to login
- print(f"[User {user_id}] Attempting login...")
- for i in range(5):
- try:
- resp = await client.post(f"{BASE_URL}/auth/login", json={
- "email": email,
- "password": password
- })
- if resp.status_code == 200:
- token = resp.json().get("access_token")
- print(f"[User {user_id}] Login successful on attempt {i+1}")
- break
- elif resp.status_code == 403:
- print(f"[User {user_id}] Login failed: Captcha required or rate limited")
- # If captcha is required, this user stops login attempts in this simple script
- return
- except Exception as e:
- print(f"[User {user_id}] Login error: {e}")
- return
- else:
- print(f"[User {user_id}] Failed to login after 5 attempts")
- return
- # 2. Connect to global websocket
- ws_uri = f"{WS_URL}/auth/ws/global?token={token}"
- try:
- async with websockets.connect(ws_uri) as ws:
- print(f"[User {user_id}] WebSocket connected")
-
- # 3. Simulate order creation (to test 1-min rate limit)
- # We try twice rapidly
- for i in range(2):
- order_data = {
- "first_name": "Test",
- "last_name": "User",
- "phone": "123456",
- "email": email,
- "shipping_address": "Test Load Street",
- "material_id": 1,
- "quantity": 1
- }
- # Need to use form-data with file
- files = {'file': ('model.stl', b'binary content stl', 'application/octet-stream')}
- resp = await client.post(f"{BASE_URL}/orders", data=order_data, files=files)
-
- if resp.status_code == 200:
- print(f"[User {user_id}] Order {i+1} created successfully")
- elif resp.status_code == 429:
- print(f"[User {user_id}] Order {i+1} REJECTED (Rate Limit Working!)")
- else:
- print(f"[User {user_id}] Order {i+1} failed: {resp.status_code}")
-
- # 4. Stay connected for a bit to receive potential updates
- # and send pings
- for _ in range(5):
- await ws.send("ping")
- try:
- # Wait for a message with timeout
- msg = await asyncio.wait_for(ws.recv(), timeout=2.0)
- print(f"[User {user_id}] WS Received: {msg[:50]}...")
- except asyncio.TimeoutError:
- pass
- await asyncio.sleep(1)
-
- except Exception as e:
- print(f"[User {user_id}] WS/Order error: {e}")
- async def main():
- print("--- Starting Load Test ---")
- start_time = time.time()
-
- # Run 10 concurrent users
- tasks = [simulate_user(i) for i in range(10)]
- await asyncio.gather(*tasks)
-
- end_time = time.time()
- print(f"--- Load Test Finished in {end_time - start_time:.2f}s ---")
- if __name__ == "__main__":
- asyncio.run(main())
|