| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- """Provider selection stays exclusive even when a backup bypasses the settings route."""
- import asyncio
- from contextlib import asynccontextmanager
- from types import SimpleNamespace
- from unittest.mock import AsyncMock, patch
- import pytest
- from backend.app.models.settings import Settings
- from backend.app.services.github_restore import GitHubRestoreService, _CategoryTally
- from backend.app.services.obico_detection import ObicoDetectionService
- from backend.app.services.octoeverywhere_detection import OctoEverywhereDetectionService
- @pytest.fixture
- def detectors(db_session):
- @asynccontextmanager
- async def session():
- yield db_session
- obico = ObicoDetectionService()
- octoeverywhere = OctoEverywhereDetectionService()
- with (
- patch("backend.app.services.obico_detection.async_session", session),
- patch("backend.app.services.octoeverywhere_detection.async_session", session),
- ):
- yield obico, octoeverywhere
- obico.stop()
- octoeverywhere.stop()
- @pytest.mark.parametrize(
- ("obico_flag", "octoeverywhere_flag", "expected"),
- [
- ("false", "false", (False, False)),
- ("true", "false", (True, False)),
- ("false", "true", (False, True)),
- ("true", "true", (False, False)),
- ("true", None, (True, False)),
- (None, "true", (False, True)),
- (None, None, (False, False)),
- ],
- )
- async def test_provider_selection_from_saved_flags(db_session, detectors, obico_flag, octoeverywhere_flag, expected):
- for key, value in (("obico_enabled", obico_flag), ("octoeverywhere_enabled", octoeverywhere_flag)):
- if value is not None:
- db_session.add(Settings(key=key, value=value))
- await db_session.commit()
- loaded = [await detector._load_settings() for detector in detectors]
- assert tuple(settings["enabled"] for settings in loaded) == expected
- async def test_legacy_restore_never_starts_both_providers_even_with_cached_settings(db_session, detectors):
- obico, octoeverywhere = detectors
- db_session.add_all(
- Settings(key=key, value=value)
- for key, value in {
- "obico_enabled": "false",
- "obico_ml_url": "http://obico.local:3333",
- "octoeverywhere_enabled": "true",
- "octoeverywhere_api_key": "test-key",
- }.items()
- )
- await db_session.commit()
- octoeverywhere._cache_settings(await octoeverywhere._load_settings())
- assert octoeverywhere._settings["enabled"] is True
- tally, written = _CategoryTally(), set()
- await GitHubRestoreService()._restore_settings(
- db_session, {"settings": {"obico_enabled": "true"}}, overwrite=True, tally=tally, keys_written=written
- )
- await db_session.commit()
- assert written == {"obico_enabled"}
- # Stop after one scheduler tick, retaining normal event-loop yields used by
- # the database driver and the independently scheduled printer check.
- original_sleep = asyncio.sleep
- async def one_tick(delay):
- if delay > 0:
- raise asyncio.CancelledError
- await original_sleep(0)
- obico._check_printer = AsyncMock()
- octoeverywhere._check_printer = AsyncMock()
- with (
- patch("backend.app.services.printer_manager.printer_manager") as manager,
- patch("asyncio.sleep", one_tick),
- ):
- manager.get_all_statuses.return_value = {1: SimpleNamespace(state="RUNNING", task_name="test-print")}
- manager.is_connected.return_value = True
- await obico._loop()
- await octoeverywhere._loop()
- await asyncio.gather(*octoeverywhere._checks.values())
- obico._check_printer.assert_not_awaited()
- octoeverywhere._check_printer.assert_awaited_once()
- # At its next normal settings refresh, OctoEverywhere also sees the
- # conflicting selection and stops inspecting, without a process restart.
- octoeverywhere._settings_refresh_at = 0
- await octoeverywhere._loop()
- await obico._loop()
- assert octoeverywhere._settings["enabled"] is False
- obico._check_printer.assert_not_awaited()
- octoeverywhere._check_printer.assert_awaited_once()
|