384 lines
15 KiB
Python
384 lines
15 KiB
Python
import pytest
|
|
from nanoid import generate as generate_nanoid
|
|
|
|
from src import models
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
class TestDeriverStatusEndpoint:
|
|
"""Test suite for the /deriver/status endpoint"""
|
|
|
|
async def test_get_deriver_status_peer_only(self, client, db_session, sample_data):
|
|
"""Test getting deriver status filtered by peer only"""
|
|
test_workspace, test_peer = sample_data
|
|
|
|
response = client.get(
|
|
f"/v2/workspaces/{test_workspace.name}/deriver/status?peer_id={test_peer.name}"
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
# Check response structure matches DeriverStatus schema
|
|
assert "peer_id" in data
|
|
assert "total_work_units" in data
|
|
assert "completed_work_units" in data
|
|
assert "in_progress_work_units" in data
|
|
assert "pending_work_units" in data
|
|
assert data["peer_id"] == test_peer.name
|
|
assert isinstance(data["total_work_units"], int)
|
|
assert isinstance(data["completed_work_units"], int)
|
|
assert isinstance(data["in_progress_work_units"], int)
|
|
assert isinstance(data["pending_work_units"], int)
|
|
|
|
async def test_get_deriver_status_session_only(
|
|
self, client, db_session, sample_data
|
|
):
|
|
"""Test getting deriver status filtered by session only"""
|
|
test_workspace, test_peer = sample_data
|
|
|
|
# Create a test session
|
|
test_session = models.Session(
|
|
workspace_name=test_workspace.name, name=str(generate_nanoid())
|
|
)
|
|
db_session.add(test_session)
|
|
await db_session.commit()
|
|
|
|
response = client.get(
|
|
f"/v2/workspaces/{test_workspace.name}/deriver/status?session_id={test_session.name}"
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
# Check response structure
|
|
assert "session_id" in data
|
|
assert "total_work_units" in data
|
|
assert "completed_work_units" in data
|
|
assert "in_progress_work_units" in data
|
|
assert "pending_work_units" in data
|
|
assert data["session_id"] == test_session.name
|
|
assert isinstance(data["total_work_units"], int)
|
|
|
|
async def test_get_deriver_status_peer_and_session(
|
|
self, client, db_session, sample_data
|
|
):
|
|
"""Test getting deriver status filtered by both peer and session"""
|
|
test_workspace, test_peer = sample_data
|
|
|
|
# Create a test session
|
|
test_session = models.Session(
|
|
workspace_name=test_workspace.name, name=str(generate_nanoid())
|
|
)
|
|
db_session.add(test_session)
|
|
await db_session.commit()
|
|
|
|
response = client.get(
|
|
f"/v2/workspaces/{test_workspace.name}/deriver/status?peer_id={test_peer.name}&session_id={test_session.name}"
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
# Should have both peer_id and session_id in response
|
|
assert data["peer_id"] == test_peer.name
|
|
assert data["session_id"] == test_session.name
|
|
assert "total_work_units" in data
|
|
assert "completed_work_units" in data
|
|
assert "in_progress_work_units" in data
|
|
assert "pending_work_units" in data
|
|
|
|
async def test_get_deriver_status_with_include_sender_true(
|
|
self, client, db_session, sample_data
|
|
):
|
|
"""Test getting deriver status with include_sender=True"""
|
|
test_workspace, test_peer = sample_data
|
|
|
|
response = client.get(
|
|
f"/v2/workspaces/{test_workspace.name}/deriver/status?peer_id={test_peer.name}&include_sender=true"
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
assert data["peer_id"] == test_peer.name
|
|
assert "total_work_units" in data
|
|
|
|
async def test_get_deriver_status_with_include_sender_false(
|
|
self, client, db_session, sample_data
|
|
):
|
|
"""Test getting deriver status with include_sender=False (default)"""
|
|
test_workspace, test_peer = sample_data
|
|
|
|
response = client.get(
|
|
f"/v2/workspaces/{test_workspace.name}/deriver/status?peer_id={test_peer.name}&include_sender=false"
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
assert data["peer_id"] == test_peer.name
|
|
assert "total_work_units" in data
|
|
|
|
async def test_get_deriver_status_no_parameters(self, client, sample_data):
|
|
"""Test getting deriver status without required parameters returns 400"""
|
|
test_workspace, _ = sample_data
|
|
|
|
response = client.get(f"/v2/workspaces/{test_workspace.name}/deriver/status")
|
|
assert response.status_code == 400
|
|
data = response.json()
|
|
assert "detail" in data
|
|
assert (
|
|
"At least one of 'peer_id' or 'session_id' must be provided"
|
|
in data["detail"]
|
|
)
|
|
|
|
async def test_get_deriver_status_nonexistent_peer(self, client, sample_data):
|
|
"""Test getting deriver status for nonexistent peer returns empty result"""
|
|
test_workspace, _ = sample_data
|
|
nonexistent_peer = str(generate_nanoid())
|
|
|
|
response = client.get(
|
|
f"/v2/workspaces/{test_workspace.name}/deriver/status?peer_id={nonexistent_peer}"
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["peer_id"] == nonexistent_peer
|
|
assert data["total_work_units"] == 0
|
|
assert data["completed_work_units"] == 0
|
|
assert data["in_progress_work_units"] == 0
|
|
assert data["pending_work_units"] == 0
|
|
|
|
async def test_get_deriver_status_nonexistent_session(self, client, sample_data):
|
|
"""Test getting deriver status for nonexistent session returns empty result"""
|
|
test_workspace, _ = sample_data
|
|
nonexistent_session = str(generate_nanoid())
|
|
|
|
response = client.get(
|
|
f"/v2/workspaces/{test_workspace.name}/deriver/status?session_id={nonexistent_session}"
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["session_id"] == nonexistent_session
|
|
assert data["total_work_units"] == 0
|
|
assert data["completed_work_units"] == 0
|
|
assert data["in_progress_work_units"] == 0
|
|
assert data["pending_work_units"] == 0
|
|
|
|
async def test_get_deriver_status_nonexistent_workspace(self, client):
|
|
"""Test getting deriver status for nonexistent workspace returns empty result"""
|
|
nonexistent_workspace = str(generate_nanoid())
|
|
fake_peer = str(generate_nanoid())
|
|
|
|
response = client.get(
|
|
f"/v2/workspaces/{nonexistent_workspace}/deriver/status?peer_id={fake_peer}"
|
|
)
|
|
# This should return empty result since workspace/peer doesn't exist
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["peer_id"] == fake_peer
|
|
assert data["total_work_units"] == 0
|
|
assert data["completed_work_units"] == 0
|
|
assert data["in_progress_work_units"] == 0
|
|
assert data["pending_work_units"] == 0
|
|
|
|
async def test_get_deriver_status_with_queue_items(
|
|
self, client, db_session, sample_data
|
|
):
|
|
"""Test getting deriver status when there are actual queue items"""
|
|
test_workspace, test_peer = sample_data
|
|
|
|
# Create a test session
|
|
test_session = models.Session(
|
|
workspace_name=test_workspace.name, name=str(generate_nanoid())
|
|
)
|
|
db_session.add(test_session)
|
|
await db_session.flush()
|
|
|
|
# Create some queue items to test with
|
|
queue_items = [
|
|
models.QueueItem(
|
|
session_id=test_session.id,
|
|
processed=False,
|
|
payload={
|
|
"task_type": "representation",
|
|
"sender_name": test_peer.name,
|
|
"target_name": test_peer.name,
|
|
"workspace_name": test_workspace.name,
|
|
"session_name": test_session.name,
|
|
},
|
|
),
|
|
models.QueueItem(
|
|
session_id=test_session.id,
|
|
processed=True,
|
|
payload={
|
|
"task_type": "representation",
|
|
"sender_name": test_peer.name,
|
|
"target_name": test_peer.name,
|
|
"workspace_name": test_workspace.name,
|
|
"session_name": test_session.name,
|
|
},
|
|
),
|
|
]
|
|
db_session.add_all(queue_items)
|
|
await db_session.commit()
|
|
|
|
response = client.get(
|
|
f"/v2/workspaces/{test_workspace.name}/deriver/status?peer_id={test_peer.name}&session_id={test_session.name}"
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
# Should have some work units
|
|
assert data["total_work_units"] >= 2
|
|
assert data["completed_work_units"] >= 1
|
|
assert data["pending_work_units"] >= 1
|
|
|
|
async def test_get_deriver_status_with_sessions_breakdown(
|
|
self, client, db_session, sample_data
|
|
):
|
|
"""Test getting deriver status shows sessions breakdown when appropriate"""
|
|
test_workspace, test_peer = sample_data
|
|
|
|
# Create multiple test sessions
|
|
test_session1 = models.Session(
|
|
workspace_name=test_workspace.name, name=str(generate_nanoid())
|
|
)
|
|
test_session2 = models.Session(
|
|
workspace_name=test_workspace.name, name=str(generate_nanoid())
|
|
)
|
|
db_session.add_all([test_session1, test_session2])
|
|
await db_session.flush()
|
|
|
|
# Create queue items for different sessions
|
|
queue_items = [
|
|
models.QueueItem(
|
|
session_id=test_session1.id,
|
|
processed=False,
|
|
payload={
|
|
"task_type": "representation",
|
|
"sender_name": test_peer.name,
|
|
"target_name": test_peer.name,
|
|
"workspace_name": test_workspace.name,
|
|
},
|
|
),
|
|
models.QueueItem(
|
|
session_id=test_session2.id,
|
|
processed=True,
|
|
payload={
|
|
"task_type": "representation",
|
|
"sender_name": test_peer.name,
|
|
"target_name": test_peer.name,
|
|
"workspace_name": test_workspace.name,
|
|
},
|
|
),
|
|
]
|
|
db_session.add_all(queue_items)
|
|
await db_session.commit()
|
|
|
|
# Get status for peer only (should include sessions breakdown)
|
|
response = client.get(
|
|
f"/v2/workspaces/{test_workspace.name}/deriver/status?peer_id={test_peer.name}"
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
# Should have sessions breakdown when querying by peer only
|
|
if "sessions" in data and data["sessions"]:
|
|
assert isinstance(data["sessions"], dict)
|
|
# Each session should have its own status
|
|
for _, session_data in data["sessions"].items():
|
|
assert "total_work_units" in session_data
|
|
assert "completed_work_units" in session_data
|
|
assert "in_progress_work_units" in session_data
|
|
assert "pending_work_units" in session_data
|
|
|
|
async def test_get_deriver_status_empty_parameters(self, client, sample_data):
|
|
"""Test various edge cases with empty or invalid parameters"""
|
|
test_workspace, _ = sample_data
|
|
|
|
# Test with empty peer_id
|
|
response = client.get(
|
|
f"/v2/workspaces/{test_workspace.name}/deriver/status?peer_id="
|
|
)
|
|
assert response.status_code == 400
|
|
|
|
# Test with empty session_id
|
|
response = client.get(
|
|
f"/v2/workspaces/{test_workspace.name}/deriver/status?session_id="
|
|
)
|
|
assert response.status_code == 400
|
|
|
|
async def test_get_deriver_status_boolean_parameter_variations(
|
|
self, client, sample_data
|
|
):
|
|
"""Test different boolean parameter formats for include_sender"""
|
|
test_workspace, test_peer = sample_data
|
|
|
|
# Test with string 'true'
|
|
response = client.get(
|
|
f"/v2/workspaces/{test_workspace.name}/deriver/status?peer_id={test_peer.name}&include_sender=true"
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
# Test with string 'false'
|
|
response = client.get(
|
|
f"/v2/workspaces/{test_workspace.name}/deriver/status?peer_id={test_peer.name}&include_sender=false"
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
# Test with boolean True
|
|
response = client.get(
|
|
f"/v2/workspaces/{test_workspace.name}/deriver/status?peer_id={test_peer.name}&include_sender=True"
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
# Test with boolean False
|
|
response = client.get(
|
|
f"/v2/workspaces/{test_workspace.name}/deriver/status?peer_id={test_peer.name}&include_sender=False"
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
async def test_get_deriver_status_response_consistency(
|
|
self, client, db_session, sample_data
|
|
):
|
|
"""Test that response structure is consistent across different parameter combinations"""
|
|
test_workspace, test_peer = sample_data
|
|
|
|
# Create a test session
|
|
test_session = models.Session(
|
|
workspace_name=test_workspace.name, name=str(generate_nanoid())
|
|
)
|
|
db_session.add(test_session)
|
|
await db_session.commit()
|
|
|
|
# Test different parameter combinations and ensure consistent response structure
|
|
test_cases = [
|
|
f"?peer_id={test_peer.name}",
|
|
f"?session_id={test_session.name}",
|
|
f"?peer_id={test_peer.name}&session_id={test_session.name}",
|
|
f"?peer_id={test_peer.name}&include_sender=true",
|
|
f"?session_id={test_session.name}&include_sender=false",
|
|
]
|
|
|
|
for params in test_cases:
|
|
response = client.get(
|
|
f"/v2/workspaces/{test_workspace.name}/deriver/status{params}"
|
|
)
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
# All responses should have these base fields
|
|
assert "total_work_units" in data
|
|
assert "completed_work_units" in data
|
|
assert "in_progress_work_units" in data
|
|
assert "pending_work_units" in data
|
|
|
|
# Verify counts are non-negative integers
|
|
assert data["total_work_units"] >= 0
|
|
assert data["completed_work_units"] >= 0
|
|
assert data["in_progress_work_units"] >= 0
|
|
assert data["pending_work_units"] >= 0
|
|
|
|
# Verify total equals sum of components
|
|
assert data["total_work_units"] == (
|
|
data["completed_work_units"]
|
|
+ data["in_progress_work_units"]
|
|
+ data["pending_work_units"]
|
|
)
|