jw-search / backend /tests /test_db_runtime_paths.py
jw-tools's picture
deploy: latest main (lazy-ML cold start, durable launcher, web-image search, scene search) + full-app data refresh
7ea1851 verified
Raw
History Blame Contribute Delete
5.53 kB
"""
Regression tests for shared database path and schema helpers.
"""
import os
import sys
# Add backend to path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import db_utils
import runtime_paths
import settings
def test_runtime_db_paths_follow_shared_directory_overrides(tmp_path, monkeypatch):
data_root = tmp_path / "data-root"
db_root = tmp_path / "db-root"
custom_settings = tmp_path / "custom" / "settings.sqlite"
monkeypatch.setenv("SEARCH_UI_DATA_ROOT", str(data_root))
monkeypatch.delenv("SEARCH_UI_DB_DIR", raising=False)
monkeypatch.delenv("SEARCH_UI_SEARCH_DB_PATH", raising=False)
monkeypatch.delenv("SEARCH_UI_IMAGE_DB_PATH", raising=False)
monkeypatch.delenv("SEARCH_UI_FACE_DB_PATH", raising=False)
monkeypatch.delenv("SEARCH_UI_SPEAKER_DB_PATH", raising=False)
monkeypatch.delenv("SEARCH_UI_SETTINGS_DB_PATH", raising=False)
assert runtime_paths.get_db_dir() == str(data_root)
assert runtime_paths.get_search_db_path() == str(data_root / "database.db")
assert runtime_paths.get_image_db_path() == str(data_root / "images_database.db")
assert runtime_paths.get_face_db_path() == str(data_root / "faces_database.db")
assert runtime_paths.get_speaker_db_path() == str(data_root / "speakers_database.db")
assert runtime_paths.get_settings_db_path() == str(data_root / "settings.db")
assert runtime_paths.get_publications_db_path() == str(data_root / "publications_database.db")
assert runtime_paths.get_json_dir() == str(data_root / "json")
assert runtime_paths.get_subtitles_dir() == str(data_root / "subtitles")
assert runtime_paths.get_videos_dir() == str(data_root / "videos")
assert runtime_paths.get_publications_dir() == str(data_root / "publications")
assert runtime_paths.get_logs_dir() == str(data_root / "logs")
assert runtime_paths.get_checkpoints_dir() == str(data_root / "checkpoints")
monkeypatch.setenv("SEARCH_UI_DB_DIR", str(db_root))
monkeypatch.setenv("SEARCH_UI_SETTINGS_DB_PATH", str(custom_settings))
assert runtime_paths.get_db_dir() == str(db_root)
assert runtime_paths.get_search_db_path() == str(db_root / "database.db")
assert runtime_paths.get_settings_db_path() == str(custom_settings)
def test_connect_sqlite_creates_parent_dir_and_stores_schema_metadata(tmp_path):
db_path = tmp_path / "nested" / "app.db"
conn = db_utils.connect_sqlite(str(db_path))
db_utils.register_schema_metadata(
conn,
db_name="unit_test_db",
schema_version=7,
embedding_type="binary",
embedding_model="test-model-v1",
embedding_recipe={"recipe_version": 1, "model_name": "test-model-v1"},
)
conn.commit()
metadata = db_utils.fetch_schema_metadata(conn, "unit_test_db")
conn.close()
assert db_path.exists()
assert metadata == {
"db_name": "unit_test_db",
"schema_version": 7,
"embedding_type": "binary",
"embedding_model": "test-model-v1",
"embedding_recipe": {"recipe_version": 1, "model_name": "test-model-v1"},
"created_at": metadata["created_at"],
}
assert metadata["created_at"]
def test_register_schema_metadata_migrates_existing_table_for_recipe(tmp_path):
db_path = tmp_path / "legacy.db"
conn = db_utils.connect_sqlite(str(db_path))
conn.execute(
"""
CREATE TABLE _schema_metadata (
db_name TEXT PRIMARY KEY,
schema_version INTEGER NOT NULL DEFAULT 1,
embedding_type TEXT,
embedding_model TEXT,
created_at TEXT
)
"""
)
conn.commit()
db_utils.register_schema_metadata(
conn,
db_name="legacy_db",
schema_version=2,
embedding_type="binary",
embedding_model="legacy-model",
embedding_recipe={"recipe_version": 9},
)
conn.commit()
metadata = db_utils.fetch_schema_metadata(conn, "legacy_db")
columns = {
row[1]
for row in conn.execute("PRAGMA table_info(_schema_metadata)").fetchall()
}
conn.close()
assert "embedding_recipe" in columns
assert metadata["embedding_recipe"] == {"recipe_version": 9}
def test_settings_init_db_tracks_initialized_paths_per_database(tmp_path, monkeypatch):
first_path = tmp_path / "settings-a" / "settings.db"
second_path = tmp_path / "settings-b" / "settings.db"
monkeypatch.setattr(settings, "_initialized_db_paths", set())
monkeypatch.setenv("SEARCH_UI_SETTINGS_DB_PATH", str(first_path))
settings.init_settings_db()
monkeypatch.setenv("SEARCH_UI_SETTINGS_DB_PATH", str(second_path))
settings.init_settings_db()
assert first_path.exists()
assert second_path.exists()
first_conn = db_utils.connect_sqlite(str(first_path))
second_conn = db_utils.connect_sqlite(str(second_path))
try:
first_tables = {
row[0]
for row in first_conn.execute(
"SELECT name FROM sqlite_master WHERE type = 'table'"
).fetchall()
}
second_tables = {
row[0]
for row in second_conn.execute(
"SELECT name FROM sqlite_master WHERE type = 'table'"
).fetchall()
}
finally:
first_conn.close()
second_conn.close()
assert "global_settings" in first_tables
assert "global_settings" in second_tables
assert settings._initialized_db_paths == {str(first_path), str(second_path)}