mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-11-12 20:15:10 +00:00
Vaults.add_keys and kv add skip null content keys instead of failing the batch; is_null_key moves to core.vault. A manifest snapshot restore has one 32 MiB inflate budget. Tests reset the speed limiter and config between runs.
82 lines
3.0 KiB
Python
82 lines
3.0 KiB
Python
"""Pins the SIGHUP config reload: a valid file swaps the users in, a bad or restart-only file leaves the old one."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
import yaml
|
|
from aiohttp import web
|
|
|
|
from unshackle.commands import serve as serve_cmd
|
|
from unshackle.core import config as config_module
|
|
from unshackle.core.config import config
|
|
|
|
pytestmark = pytest.mark.unit
|
|
|
|
LOG = logging.getLogger("serve")
|
|
|
|
|
|
@pytest.fixture
|
|
def running(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> tuple[web.Application, Path]:
|
|
"""An app serving the key ``old`` with one open CDM session, and a writable config path."""
|
|
wvds = tmp_path / "wvds"
|
|
prds = tmp_path / "prds"
|
|
wvds.mkdir()
|
|
prds.mkdir()
|
|
(wvds / "dev.wvd").write_bytes(b"x")
|
|
# a valid reload replaces every config section, so put each one back for the next test
|
|
for name, value in list(vars(config).items()):
|
|
monkeypatch.setattr(config, name, value)
|
|
monkeypatch.setattr(config.directories, "wvds", wvds)
|
|
monkeypatch.setattr(config.directories, "prds", prds)
|
|
monkeypatch.setattr(config, "serve", {"api_secret": "api", "users": {"old": {"devices": ["dev"]}}})
|
|
path = tmp_path / "unshackle.yaml"
|
|
monkeypatch.setattr(config_module, "config_path", path)
|
|
|
|
app = web.Application()
|
|
app["config"] = {"users": {"old": {"devices": ["dev"]}, "api": {"devices": ["dev"]}}, "devices": {}}
|
|
app["cdms"] = {("old", "dev"): object()}
|
|
return app, path
|
|
|
|
|
|
def _write(path: Path, **serve: object) -> None:
|
|
path.write_text(yaml.safe_dump({"serve": {"api_secret": "api", **serve}}), encoding="utf8")
|
|
|
|
|
|
def _reload(app: web.Application) -> bool:
|
|
return serve_cmd.reload_config(app, no_key=False, serve_widevine=True, serve_playready=True)
|
|
|
|
|
|
def test_valid_reload_swaps_the_accepted_keys(running: tuple[web.Application, Path]) -> None:
|
|
app, path = running
|
|
_write(path, users={"new": {"devices": ["dev"]}})
|
|
|
|
assert _reload(app) is True
|
|
assert set(app["config"]["users"]) == {"new", "api"}
|
|
assert app["config"]["devices"] == {"dev": path.parent / "wvds" / "dev.wvd"}
|
|
assert config.serve["users"] == {"new": {"devices": ["dev"]}}
|
|
assert ("old", "dev") in app["cdms"]
|
|
|
|
|
|
def test_invalid_file_keeps_the_running_config(running: tuple[web.Application, Path]) -> None:
|
|
app, path = running
|
|
_write(path, users={"new": {"devices": ["dev"], "tier": "gold"}})
|
|
|
|
assert _reload(app) is False
|
|
assert set(app["config"]["users"]) == {"old", "api"}
|
|
assert config.serve["users"] == {"old": {"devices": ["dev"]}}
|
|
|
|
|
|
def test_restart_only_change_is_reported_not_applied(
|
|
running: tuple[web.Application, Path], caplog: pytest.LogCaptureFixture
|
|
) -> None:
|
|
app, path = running
|
|
_write(path, users={"new": {"devices": ["dev"]}}, remote_only=True)
|
|
|
|
with caplog.at_level(logging.WARNING, logger=LOG.name):
|
|
assert _reload(app) is False
|
|
assert "restart" in caplog.text and "remote_only" in caplog.text
|
|
assert set(app["config"]["users"]) == {"old", "api"}
|