import pytest @pytest.mark.anyio async def test_list_default_placement_policies(api_client) -> None: response = await api_client.get("/api/policies/placement") assert response.status_code == 200 items = response.json()["items"] assert {item["file_class"] for item in items} == {"document", "image", "other", "video"} video_policy = next(item for item in items if item["file_class"] == "video") assert video_policy["preferred_backend_ids"] == [] assert video_policy["excluded_backend_ids"] == [] assert video_policy["max_non_local_size_bytes"] is None for policy in items: desired_total_replicas = ( int(policy["require_local"]) + policy["stable_replica_count"] + policy["opportunistic_replica_count"] ) assert desired_total_replicas == 2 @pytest.mark.anyio async def test_update_policy_and_preview_decision(api_client) -> None: stable_a = await api_client.post( "/api/backends", json={ "name": "s3-stable-a", "type": "s3", "stability_class": "stable", "read_priority": 80, "write_priority": 80, "config": {"bucket": "stable-a"}, }, ) stable_b = await api_client.post( "/api/backends", json={ "name": "s3-stable-b", "type": "s3", "stability_class": "stable", "read_priority": 90, "write_priority": 90, "config": {"bucket": "stable-b"}, }, ) opportunistic = await api_client.post( "/api/backends", json={ "name": "s3-opp", "type": "s3", "stability_class": "opportunistic", "read_priority": 70, "write_priority": 70, "config": {"bucket": "opp"}, }, ) stable_a_id = stable_a.json()["backend"]["id"] stable_b_id = stable_b.json()["backend"]["id"] opportunistic_id = opportunistic.json()["backend"]["id"] update_response = await api_client.put( "/api/policies/placement/video", json={ "require_local": True, "stable_replica_count": 1, "opportunistic_replica_count": 1, "preferred_backend_ids": [opportunistic_id, stable_b_id], "excluded_backend_ids": [stable_a_id], "max_non_local_size_bytes": 16, }, ) assert update_response.status_code == 200 assert update_response.json()["policy"]["preferred_backend_ids"] == [opportunistic_id, stable_b_id] assert update_response.json()["reconcile_enqueued_jobs"] == 1 jobs_response = await api_client.get("/api/jobs") assert jobs_response.status_code == 200 assert any(item["kind"] == "reconcile_all_files" for item in jobs_response.json()["items"]) preview_response = await api_client.get( "/api/policies/placement/preview", params={"mime_type": "video/mp4", "size_bytes": 8}, ) assert preview_response.status_code == 200 selected_backend_ids = [item["id"] for item in preview_response.json()["selected_backends"]] assert selected_backend_ids[0] == "bkd_local_default" assert stable_b_id in selected_backend_ids assert opportunistic_id in selected_backend_ids assert stable_a_id not in selected_backend_ids assert preview_response.json()["non_local_allowed"] is True capped_preview_response = await api_client.get( "/api/policies/placement/preview", params={"mime_type": "video/mp4", "size_bytes": 32}, ) assert capped_preview_response.status_code == 200 assert capped_preview_response.json()["selected_backends"] == [ { "id": "bkd_local_default", "name": "local-default", "type": "local_directory", "stability_class": "local", "read_priority": 100, "write_priority": 100, } ] assert capped_preview_response.json()["non_local_allowed"] is False @pytest.mark.anyio async def test_policy_rejects_overlapping_backend_preferences(api_client) -> None: backend_response = await api_client.post( "/api/backends", json={ "name": "s3-stable-a", "type": "s3", "stability_class": "stable", "read_priority": 80, "write_priority": 80, "config": {"bucket": "stable-a"}, }, ) backend_id = backend_response.json()["backend"]["id"] response = await api_client.put( "/api/policies/placement/document", json={ "require_local": True, "stable_replica_count": 1, "opportunistic_replica_count": 0, "preferred_backend_ids": [backend_id], "excluded_backend_ids": [backend_id], "max_non_local_size_bytes": None, }, ) assert response.status_code == 400 assert response.json()["error"]["code"] == "placement_policy_invalid"