Files
MajoorWaldi-ComfyUI-Majoor-…/tests/features/test_index_db_ops.py
T

318 lines
9.6 KiB
Python

"""
Coverage tests for index_db_ops.py.
Targets lines: 29-68, 80-96, 112-164.
"""
from __future__ import annotations
from pathlib import Path
from types import SimpleNamespace
import pytest
from mjr_am_backend.features.index import index_db_ops as dbo
from mjr_am_backend.shared import Result
# ─── helpers ────────────────────────────────────────────────────────────────
class _DB:
def __init__(self, insert_ok=True, update_ok=True, asset_id=1):
self._insert_ok = insert_ok
self._update_ok = update_ok
self._asset_id = asset_id
self._lock_called = False
self.calls = []
async def aexecute(self, sql, params):
self.calls.append((sql, params))
if "INSERT" in sql:
if not self._insert_ok:
return Result.Err("INSERT_FAILED", "db error")
return Result.Ok(self._asset_id)
if "UPDATE" in sql:
if not self._update_ok:
return Result.Err("UPDATE_FAILED", "db error")
return Result.Ok(1)
return Result.Ok(None)
class _Lock:
def __init__(self, asset_id):
self.asset_id = asset_id
async def __aenter__(self):
return self
async def __aexit__(self, exc_type, exc, tb):
return False
def lock_for_asset(self, asset_id):
return self._Lock(asset_id)
def _make_metadata_result(ok=True):
if ok:
return Result.Ok({"width": 512, "height": 768, "prompt": "test"})
return Result.Err("META_ERR", "fail")
def _make_execution_metadata_result():
return Result.Ok({
"width": 512,
"height": 768,
"job_id": "job-1",
"workflow_id": "workflow-1",
"source_node_id": "node-1",
})
# ─── add_asset ───────────────────────────────────────────────────────────────
@pytest.mark.asyncio
async def test_add_asset_success(monkeypatch):
async def _write_row(db, asset_id, metadata_result, *, filepath):
return Result.Ok(None)
monkeypatch.setattr(dbo.MetadataHelpers, "write_asset_metadata_row", _write_row)
db = _DB(insert_ok=True, asset_id=42)
scanner = SimpleNamespace(db=db, _log_scan_event=lambda *a, **kw: None)
result = await dbo.add_asset(
scanner,
filename="img.png",
subfolder="",
filepath="C:/x/img.png",
kind="image",
mtime=1000,
size=4096,
file_path=Path("C:/x/img.png"),
metadata_result=_make_metadata_result(),
write_metadata=True,
)
assert result.ok
assert result.data["action"] == "added"
assert result.data["asset_id"] == 42
@pytest.mark.asyncio
async def test_add_asset_persists_execution_metadata(monkeypatch):
async def _write_row(db, asset_id, metadata_result, *, filepath):
return Result.Ok(None)
monkeypatch.setattr(dbo.MetadataHelpers, "write_asset_metadata_row", _write_row)
db = _DB(insert_ok=True, asset_id=42)
scanner = SimpleNamespace(db=db, _log_scan_event=lambda *a, **kw: None)
result = await dbo.add_asset(
scanner,
filename="img.png",
subfolder="",
filepath="C:/x/img.png",
kind="image",
mtime=1000,
size=4096,
file_path=Path("C:/x/img.png"),
metadata_result=_make_execution_metadata_result(),
write_metadata=True,
)
assert result.ok
insert_sql, insert_params = db.calls[0]
assert "job_id, workflow_id, source_node_id" in insert_sql
assert insert_params[-3:] == ("job-1", "workflow-1", "node-1")
@pytest.mark.asyncio
async def test_add_asset_insert_failure():
db = _DB(insert_ok=False)
scanner = SimpleNamespace(db=db)
result = await dbo.add_asset(
scanner,
filename="img.png",
subfolder="",
filepath="C:/img.png",
kind="image",
mtime=1000,
size=512,
file_path=Path("C:/img.png"),
metadata_result=_make_metadata_result(),
)
assert not result.ok and "INSERT_FAILED" in result.code
@pytest.mark.asyncio
async def test_add_asset_no_asset_id():
db = _DB(insert_ok=True, asset_id=None)
scanner = SimpleNamespace(db=db)
result = await dbo.add_asset(
scanner,
filename="img.png",
subfolder="",
filepath="C:/img.png",
kind="image",
mtime=1000,
size=512,
file_path=Path("C:/img.png"),
metadata_result=_make_metadata_result(),
)
assert not result.ok
# ─── write_asset_metadata_if_needed ─────────────────────────────────────────
@pytest.mark.asyncio
async def test_write_asset_metadata_if_needed_skip_lock():
scanner = SimpleNamespace()
# skip_lock=True → early return
await dbo.write_asset_metadata_if_needed(
scanner, asset_id=1, metadata_result=_make_metadata_result(),
filepath="x.png", write_metadata=True, skip_lock=True
)
@pytest.mark.asyncio
async def test_write_asset_metadata_if_needed_no_write():
scanner = SimpleNamespace()
# write_metadata=False → early return
await dbo.write_asset_metadata_if_needed(
scanner, asset_id=1, metadata_result=_make_metadata_result(),
filepath="x.png", write_metadata=False, skip_lock=False
)
@pytest.mark.asyncio
async def test_write_asset_metadata_if_needed_write_fails(monkeypatch):
async def _write_row(db, asset_id, metadata_result, *, filepath):
return Result.Err("FAIL", "write error")
monkeypatch.setattr(dbo.MetadataHelpers, "write_asset_metadata_row", _write_row)
log_calls = []
scanner = SimpleNamespace(
db=object(),
_log_scan_event=lambda level, msg, **kw: log_calls.append(msg),
)
await dbo.write_asset_metadata_if_needed(
scanner, asset_id=5, metadata_result=_make_metadata_result(),
filepath="x.png", write_metadata=True, skip_lock=False
)
assert any("Failed" in c for c in log_calls)
# ─── update_asset ────────────────────────────────────────────────────────────
@pytest.mark.asyncio
async def test_update_asset_success_with_lock(monkeypatch):
async def _write_row(db, asset_id, metadata_result, *, filepath):
return Result.Ok(None)
monkeypatch.setattr(dbo.MetadataHelpers, "write_asset_metadata_row", _write_row)
db = _DB(update_ok=True)
scanner = SimpleNamespace(db=db, _log_scan_event=lambda *a, **kw: None)
result = await dbo.update_asset(
scanner,
asset_id=1,
file_path=Path("C:/x.png"),
mtime=2000,
size=1024,
metadata_result=_make_metadata_result(),
write_metadata=True,
skip_lock=False,
)
assert result.ok and result.data["action"] == "updated"
@pytest.mark.asyncio
async def test_update_asset_persists_execution_metadata(monkeypatch):
async def _write_row(db, asset_id, metadata_result, *, filepath):
return Result.Ok(None)
monkeypatch.setattr(dbo.MetadataHelpers, "write_asset_metadata_row", _write_row)
db = _DB(update_ok=True)
scanner = SimpleNamespace(db=db, _log_scan_event=lambda *a, **kw: None)
result = await dbo.update_asset(
scanner,
asset_id=1,
file_path=Path("C:/x.png"),
mtime=2000,
size=1024,
metadata_result=_make_execution_metadata_result(),
write_metadata=True,
skip_lock=False,
)
assert result.ok
update_sql, update_params = db.calls[0]
assert "job_id = COALESCE" in update_sql
assert update_params[-4:-1] == ("job-1", "workflow-1", "node-1")
@pytest.mark.asyncio
async def test_update_asset_skip_lock(monkeypatch):
async def _write_row(db, asset_id, metadata_result, *, filepath):
return Result.Ok(None)
monkeypatch.setattr(dbo.MetadataHelpers, "write_asset_metadata_row", _write_row)
db = _DB(update_ok=True)
scanner = SimpleNamespace(db=db)
result = await dbo.update_asset(
scanner,
asset_id=2,
file_path=Path("C:/y.png"),
mtime=3000,
size=2048,
metadata_result=_make_metadata_result(),
write_metadata=True,
skip_lock=True,
)
assert result.ok
@pytest.mark.asyncio
async def test_update_asset_db_error():
db = _DB(update_ok=False)
scanner = SimpleNamespace(db=db)
result = await dbo.update_asset(
scanner,
asset_id=3,
file_path=Path("C:/z.png"),
mtime=4000,
size=512,
metadata_result=_make_metadata_result(),
write_metadata=False,
skip_lock=True,
)
assert not result.ok
@pytest.mark.asyncio
async def test_update_asset_metadata_write_fails(monkeypatch):
async def _write_row(db, asset_id, metadata_result, *, filepath):
return Result.Err("FAIL", "write error")
monkeypatch.setattr(dbo.MetadataHelpers, "write_asset_metadata_row", _write_row)
log_calls = []
db = _DB(update_ok=True)
scanner = SimpleNamespace(db=db, _log_scan_event=lambda level, msg, **kw: log_calls.append(msg))
result = await dbo.update_asset(
scanner,
asset_id=4,
file_path=Path("C:/w.png"),
mtime=5000,
size=256,
metadata_result=_make_metadata_result(),
write_metadata=True,
skip_lock=False,
)
assert result.ok
assert any("Failed" in c for c in log_calls)