"""Tests for scheduler module.""" import os import pytest from unittest.mock import patch, MagicMock from factsdb.config import Config, DatabaseConfig, AIEndpointConfig, FTPServerConfig, SchedulerConfig from factsdb.scheduler import FactExtractionJob, FactExtractionScheduler, get_scheduler class MockConfig: """Lightweight mock Config that avoids env var requirements.""" def __init__(self, db_path=":memory:"): self.database = DatabaseConfig(path=db_path) self.ai_endpoint = AIEndpointConfig(url="http://localhost", auth_token="tok") self.ftp_server = FTPServerConfig(host="0.0.0.0", port=2121, username="u", password="p") self.scheduler = SchedulerConfig(interval_minutes=10) @pytest.fixture def scheduler_config(tmp_path): return MockConfig(db_path=str(tmp_path / "sched.db")) class TestFactExtractionJob: def test_execute_missing_directory(self, scheduler_config): from factsdb.database import DatabaseManager from factsdb.file_processor import FileProcessor from factsdb.ai_processor import AIProcessor dm = DatabaseManager(scheduler_config.database) fp = FileProcessor() ap = AIProcessor(scheduler_config.ai_endpoint) job = FactExtractionJob(scheduler_config, dm, fp, ap) with pytest.raises(Exception, match="Directory does not exist"): job.execute("/nonexistent/dir", "t", "", "gpt-oss") class TestFactExtractionScheduler: def test_init(self, scheduler_config): with patch("factsdb.scheduler.AIProcessor"): with patch("factsdb.scheduler.DatabaseManager"): sched = FactExtractionScheduler(scheduler_config) assert sched.jobs == {} assert sched.is_running is False def test_add_job(self, scheduler_config): with patch("factsdb.scheduler.AIProcessor"): with patch("factsdb.scheduler.DatabaseManager"): sched = FactExtractionScheduler(scheduler_config) sched.add_job("/tmp", "t1", "", "gpt-oss", 5) jobs = sched.get_jobs() assert len(jobs) == 1 assert jobs[0]["directory_path"] == "/tmp" assert jobs[0]["interval_minutes"] == 5 def test_remove_job(self, scheduler_config): with patch("factsdb.scheduler.AIProcessor"): with patch("factsdb.scheduler.DatabaseManager"): sched = FactExtractionScheduler(scheduler_config) sched.add_job("/tmp", "t1") sched.remove_job("job_1") assert len(sched.get_jobs()) == 0 def test_is_job_running(self, scheduler_config): with patch("factsdb.scheduler.AIProcessor"): with patch("factsdb.scheduler.DatabaseManager"): sched = FactExtractionScheduler(scheduler_config) sched.add_job("/tmp", "t1") assert sched.is_job_running("job_1") is True assert sched.is_job_running("job_99") is False def test_start_stop(self, scheduler_config): with patch("factsdb.scheduler.AIProcessor"): with patch("factsdb.scheduler.DatabaseManager"): sched = FactExtractionScheduler(scheduler_config) sched.start() assert sched.is_running is True sched.stop() assert sched.is_running is False def test_get_jobs_empty(self, scheduler_config): with patch("factsdb.scheduler.AIProcessor"): with patch("factsdb.scheduler.DatabaseManager"): sched = FactExtractionScheduler(scheduler_config) assert sched.get_jobs() == [] class TestGetScheduler: def test_singleton(self, scheduler_config): import factsdb.scheduler as sched_mod sched_mod._scheduler = None with patch("factsdb.scheduler.AIProcessor"): with patch("factsdb.scheduler.DatabaseManager"): s1 = get_scheduler(scheduler_config) s2 = get_scheduler(scheduler_config) assert s1 is s2 sched_mod._scheduler = None