"""Tests for deprecation tracking module — Task 51.""" from __future__ import annotations from services.intelligence_pipeline_v3.deprecation.tracker import ( DEFAULT_DEPRECATIONS, DeprecationEntry, DeprecationStatus, DeprecationTracker, MigrationReport, ) class TestDeprecationEntry: """Task 51: Deprecation lifecycle.""" def test_create_entry(self): entry = DeprecationEntry.create( component_name="VLLMClient", component_path="services/extractor/vllm_client.py", reason="Replaced by OpenAICompatibleClient", known_consumers=["worker.py", "thesis_llm.py"], replacement="services/shared/inference/clients/openai_compatible.py", ) assert entry.status == DeprecationStatus.DEPRECATED assert entry.migration_progress == 0.0 assert not entry.all_consumers_migrated def test_mark_consumer_migrated(self): entry = DeprecationEntry.create( component_name="VLLMClient", component_path="services/extractor/vllm_client.py", reason="Replaced", known_consumers=["worker.py", "thesis_llm.py"], ) entry.mark_consumer_migrated("worker.py") assert entry.migration_progress == 0.5 entry.mark_consumer_migrated("thesis_llm.py") assert entry.migration_progress == 1.0 assert entry.all_consumers_migrated assert entry.status == DeprecationStatus.MIGRATION_COMPLETE def test_approve_removal_requires_all_migrated(self): entry = DeprecationEntry.create( component_name="v2_prompt", component_path="services/extractor/prompts.py", reason="Replaced by staged extraction", known_consumers=["worker.py"], ) # Cannot approve before migration assert not entry.approve_removal("admin") # After migration entry.mark_consumer_migrated("worker.py") assert entry.approve_removal("admin") assert entry.removal_approved def test_mark_removed(self): entry = DeprecationEntry.create( component_name="truncation", component_path="services/extractor/prompts.py", reason="Replaced by segmenter", known_consumers=["prompts.py"], ) entry.mark_consumer_migrated("prompts.py") entry.approve_removal("admin") entry.mark_removed() assert entry.status == DeprecationStatus.REMOVED assert entry.removed_at is not None def test_no_known_consumers_means_ready(self): entry = DeprecationEntry.create( component_name="old_defaults", component_path="services/shared/config.py", reason="Conflicting defaults removed", known_consumers=[], ) assert entry.all_consumers_migrated assert entry.migration_progress == 1.0 class TestDeprecationTracker: """Task 51: Full deprecation tracking workflow.""" def test_add_and_get(self): tracker = DeprecationTracker() entry = DeprecationEntry.create( component_name="VLLMClient", component_path="vllm_client.py", reason="replaced", ) tracker.add(entry) assert tracker.get("VLLMClient") is entry def test_mark_migrated(self): tracker = DeprecationTracker() entry = DeprecationEntry.create( component_name="VLLMClient", component_path="vllm_client.py", reason="replaced", known_consumers=["worker.py"], ) tracker.add(entry) assert tracker.mark_migrated("VLLMClient", "worker.py") assert tracker.get("VLLMClient").all_consumers_migrated def test_can_remove(self): tracker = DeprecationTracker() entry = DeprecationEntry.create( component_name="VLLMClient", component_path="vllm_client.py", reason="replaced", known_consumers=["worker.py"], ) tracker.add(entry) assert not tracker.can_remove("VLLMClient") tracker.mark_migrated("VLLMClient", "worker.py") assert not tracker.can_remove("VLLMClient") # Not approved yet tracker.approve_removal("VLLMClient", "admin") assert tracker.can_remove("VLLMClient") def test_pending_removals(self): tracker = DeprecationTracker() e1 = DeprecationEntry.create( "comp1", "path1", "reason", known_consumers=["c1"] ) e2 = DeprecationEntry.create( "comp2", "path2", "reason", known_consumers=["c2"] ) tracker.add(e1) tracker.add(e2) tracker.mark_migrated("comp1", "c1") tracker.approve_removal("comp1", "admin") assert len(tracker.pending_removals) == 1 assert tracker.pending_removals[0].component_name == "comp1" def test_generate_report(self): tracker = DeprecationTracker() e1 = DeprecationEntry.create( "VLLMClient", "path1", "replaced", known_consumers=["w1", "w2"] ) e2 = DeprecationEntry.create( "v2_prompt", "path2", "replaced", known_consumers=["w1"] ) tracker.add(e1) tracker.add(e2) tracker.mark_migrated("VLLMClient", "w1") tracker.mark_migrated("v2_prompt", "w1") report = tracker.generate_report() assert report.total_components == 2 assert report.deprecated == 1 # VLLMClient still has w2 assert report.migration_complete == 1 # v2_prompt is done assert len(report.blocked_removals) == 1 class TestDefaultDeprecations: """Task 51: Default deprecation entries cover required components.""" def test_default_entries_defined(self): assert len(DEFAULT_DEPRECATIONS) >= 5 def test_vllm_client_in_defaults(self): names = [d["component_name"] for d in DEFAULT_DEPRECATIONS] assert "VLLMClient" in names def test_v2_prompt_in_defaults(self): names = [d["component_name"] for d in DEFAULT_DEPRECATIONS] assert "v2_extraction_prompt" in names def test_provider_branching_in_defaults(self): names = [d["component_name"] for d in DEFAULT_DEPRECATIONS] assert "provider_branching" in names def test_truncation_in_defaults(self): names = [d["component_name"] for d in DEFAULT_DEPRECATIONS] assert "8000_char_truncation" in names def test_compatibility_adapter_in_defaults(self): names = [d["component_name"] for d in DEFAULT_DEPRECATIONS] assert "compatibility_adapter" in names class TestMigrationReport: """Task 51.5: Archive final migration reports.""" def test_report_to_dict(self): entries = [ DeprecationEntry.create("c1", "p1", "r", known_consumers=["x"]), ] report = MigrationReport.generate(entries) d = report.to_dict() assert "total_components" in d assert "blocked_removals" in d