"""``database.synchronous`` is configurable, validated, and floored on macOS. Before this, `apply_database_pragmas()` accepted five sizing pragmas and no durability one, and `_enforce_macos_synchronous_full()` returned early off Darwin. So on Linux and Windows nothing in the process ever executed `PRAGMA synchronous` against state.db, and the effective level was whichever `SQLITE_DEFAULT_WAL_SYNCHRONOUS` the interpreter's SQLite happened to be compiled with -- invisible from config, unpinnable, and different between builds. See #90837, where three weeks of corruption forensics were carried out under the stated assumption of `synchronous=FULL` on Ubuntu. """ import sqlite3 import sys import pytest import hermes_state from hermes_state import ( apply_database_pragmas, resolve_synchronous_level, ) def _wal_conn(tmp_path): conn = sqlite3.connect(str(tmp_path / "state.db"), isolation_level=None) conn.execute("PRAGMA journal_mode=WAL") return conn def _level(conn): return conn.execute("PRAGMA synchronous").fetchone()[0] def _config(monkeypatch, database_section): """Point apply_database_pragmas at an in-memory config. It imports `hermes_cli.config` lazily inside the function body, so the patch has to land on that module rather than on a name in this one. """ import hermes_cli.config as config_mod cfg = {"database": database_section} monkeypatch.setattr(config_mod, "load_config_readonly", lambda *a, **k: cfg) return cfg class TestResolveSynchronousLevel: """The parser, in isolation -- a wrong answer here is a silent downgrade.""" @pytest.mark.parametrize( "raw,expected", [ ("OFF", 0), ("NORMAL", 1), ("FULL", 2), ("EXTRA", 3), ("full", 2), ("Full", 2), (" FULL ", 2), (0, 0), (1, 1), (2, 2), (3, 3), ("2", 2), (" 2 ", 2), ], ) def test_accepts_documented_spellings(self, raw, expected): assert resolve_synchronous_level(raw) == expected @pytest.mark.parametrize( "raw", [ "PARANOID", "", " ", 4, -1, "4", None, [], {}, 2.5, "2.0", ], ) def test_rejects_everything_else(self, raw): assert resolve_synchronous_level(raw) is None def test_yaml_off_is_a_level_but_yaml_on_is_not(self): """`synchronous: off` is bool False in YAML and means OFF. `synchronous: on` is bool True and means nothing -- there is no durability level it could map to, so it must be rejected rather than coerced to 1 by int(True). """ assert resolve_synchronous_level(False) == 0 assert resolve_synchronous_level(True) is None class TestAppliedFromConfig: def test_configured_level_reaches_the_connection(self, tmp_path, monkeypatch): _config(monkeypatch, {"synchronous": "NORMAL"}) conn = _wal_conn(tmp_path) try: monkeypatch.setattr(sys, "platform", "linux") apply_database_pragmas(conn, db_label="state.db") assert _level(conn) == 1 finally: conn.close() def test_full_reaches_the_connection(self, tmp_path, monkeypatch): """The #90837 case: an operator asking for FULL on Linux gets FULL. Fails without the patch -- the pragma was never executed at all, so the connection kept whatever the build's default was. """ _config(monkeypatch, {"synchronous": "FULL"}) conn = _wal_conn(tmp_path) try: monkeypatch.setattr(sys, "platform", "linux") conn.execute("PRAGMA synchronous=0") assert _level(conn) == 0 apply_database_pragmas(conn, db_label="state.db") assert _level(conn) == 2 finally: conn.close() def test_unset_leaves_the_level_alone(self, tmp_path, monkeypatch): """No config key must mean no write -- this is the default path.""" _config(monkeypatch, {"wal_autocheckpoint": 1000}) conn = _wal_conn(tmp_path) try: monkeypatch.setattr(sys, "platform", "linux") conn.execute("PRAGMA synchronous=0") apply_database_pragmas(conn, db_label="state.db") assert _level(conn) == 0 assert conn.execute("PRAGMA wal_autocheckpoint").fetchone()[0] == 1000 finally: conn.close() def test_garbage_warns_and_changes_nothing(self, tmp_path, monkeypatch, caplog): """A typo must not fall through to a different durability level.""" _config(monkeypatch, {"synchronous": "PARANOID"}) conn = _wal_conn(tmp_path) try: monkeypatch.setattr(sys, "platform", "linux") conn.execute("PRAGMA synchronous=2") with caplog.at_level("WARNING"): apply_database_pragmas(conn, db_label="state.db") assert _level(conn) == 2 assert "PARANOID" in caplog.text finally: conn.close() def test_the_other_pragmas_still_apply(self, tmp_path, monkeypatch): """Guardrail for #77630's five keys -- they share the same function.""" _config( monkeypatch, {"synchronous": "FULL", "wal_autocheckpoint": 250, "mmap_size": 0}, ) conn = _wal_conn(tmp_path) try: monkeypatch.setattr(sys, "platform", "linux") apply_database_pragmas(conn, db_label="state.db") assert _level(conn) == 2 assert conn.execute("PRAGMA wal_autocheckpoint").fetchone()[0] == 250 assert conn.execute("PRAGMA mmap_size").fetchone()[0] == 0 finally: conn.close() class TestMacOSFloor: """#64355 enforced FULL on Darwin. Config must not be able to undo it. `_enforce_macos_synchronous_full()` runs inside `apply_wal_with_fallback()`, which is earlier than `apply_database_pragmas()`, so without an explicit floor the config value would simply win by running last. """ def test_lowering_below_full_is_refused_on_darwin( self, tmp_path, monkeypatch, caplog ): _config(monkeypatch, {"synchronous": "NORMAL"}) conn = _wal_conn(tmp_path) try: monkeypatch.setattr(sys, "platform", "darwin") hermes_state._enforce_macos_synchronous_full(conn) assert _level(conn) == 2 with caplog.at_level("WARNING"): apply_database_pragmas(conn, db_label="state.db") assert _level(conn) == 2, "config lowered the macOS btree protection" assert "macOS" in caplog.text finally: conn.close() def test_raising_above_full_is_allowed_on_darwin(self, tmp_path, monkeypatch): """The floor is a floor, not a pin -- EXTRA is strictly safer.""" _config(monkeypatch, {"synchronous": "EXTRA"}) conn = _wal_conn(tmp_path) try: monkeypatch.setattr(sys, "platform", "darwin") apply_database_pragmas(conn, db_label="state.db") assert _level(conn) == 3 finally: conn.close() def test_the_floor_does_not_apply_off_darwin(self, tmp_path, monkeypatch): """Linux operators may deliberately choose NORMAL for write volume.""" _config(monkeypatch, {"synchronous": "NORMAL"}) conn = _wal_conn(tmp_path) try: monkeypatch.setattr(sys, "platform", "linux") conn.execute("PRAGMA synchronous=2") apply_database_pragmas(conn, db_label="state.db") assert _level(conn) == 1 finally: conn.close() def test_example_config_documents_the_key(): """An unpinnable durability level is the bug; docs are half the fix.""" from pathlib import Path text = Path(__file__).resolve().parents[1] / "cli-config.yaml.example" body = text.read_text(encoding="utf-8") assert "synchronous: FULL" in body def test_example_config_calls_the_darwin_rule_a_floor_not_a_pin(): """The macOS wording has to match _apply_synchronous_pragma's actual rule. Saying macOS is "always held at FULL" reads as "your setting is ignored here", which would talk an operator out of choosing EXTRA -- the one level that IS honored on Darwin. Only sub-FULL values are refused. The wording is the whole interface for a key nobody can otherwise observe, so pin the distinction rather than just the key's presence. """ from pathlib import Path body = ( Path(__file__).resolve().parents[1] / "cli-config.yaml.example" ).read_text(encoding="utf-8") assert "floor, not a pin" in body assert "EXTRA is honored" in body assert "always held" not in body