aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/tests/test_index_progress.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-node/tests/test_index_progress.py')
-rw-r--r--packages/meshbay-node/tests/test_index_progress.py57
1 files changed, 48 insertions, 9 deletions
diff --git a/packages/meshbay-node/tests/test_index_progress.py b/packages/meshbay-node/tests/test_index_progress.py
index ecdc223..2fa8a5c 100644
--- a/packages/meshbay-node/tests/test_index_progress.py
+++ b/packages/meshbay-node/tests/test_index_progress.py
@@ -14,7 +14,7 @@ from fastapi.testclient import TestClient
from meshbay_node.config import Config, HubConfig, KeystoreConfig, NodeConfig
from meshbay_node.daemon import NodeDaemon
from meshbay_node.indexer.group_index import GroupIndex
-from meshbay_node.indexer.indexer import IndexProgress
+from meshbay_node.indexer.indexer import NO_ANSWER, IndexProgress, UnreadFile
from meshbay_node.transport.webrtc_server import WebRTCPeerSession
from meshbay_node.ui.app import create_ui_app
@@ -64,19 +64,30 @@ def _ui_client(state: dict) -> TestClient:
"indexes": {}, **state}))
+def _indexer(progress: IndexProgress, *, unread=(), stalled=None, slow=None) -> MagicMock:
+ """What the routes read off an indexer, with nothing wrong unless said."""
+ indexer = MagicMock()
+ indexer.progress = progress
+ indexer.unread = {u.path: u for u in unread}
+ indexer.unread_count.return_value = len(indexer.unread)
+ indexer.stalled = dict(stalled or {})
+ indexer.disk_wait.return_value = slow
+ return indexer
+
+
def test_index_status_route_idle_for_unknown_group():
client = _ui_client({"indexers": {}})
resp = client.get("/api/groups/unknown-group/index-status")
assert resp.status_code == 200
assert resp.json() == {"scanning": False, "scanned_bytes": 0,
- "total_bytes": 0, "current_dir": ""}
+ "total_bytes": 0, "current_dir": "",
+ "unread": [], "unread_total": 0, "stalled": []}
def test_index_status_route_reflects_indexer_progress():
- fake_indexer = MagicMock()
- fake_indexer.progress = IndexProgress(
+ fake_indexer = _indexer(IndexProgress(
scanning=True, scanned_bytes=1_000_000, total_bytes=4_000_000_000,
- current_dir="2024")
+ current_dir="2024"))
client = _ui_client({"indexers": {"g" * 32: fake_indexer}})
resp = client.get(f"/api/groups/{'g' * 32}/index-status")
@@ -84,20 +95,47 @@ def test_index_status_route_reflects_indexer_progress():
assert resp.json() == {
"scanning": True, "scanned_bytes": 1_000_000,
"total_bytes": 4_000_000_000, "current_dir": "2024",
+ "unread": [], "unread_total": 0, "stalled": [],
}
+def test_the_operator_is_shown_what_a_scan_could_not_read_and_where_it_stopped():
+ """On the node's own machine only: these are paths. A scan that sat still
+ used to say nothing about the file it sat on, and a file it gave up on was
+ one line in a log the operator does not read."""
+ silent = UnreadFile(path="/srv/music/a/one.flac", root="music", reason=NO_ANSWER,
+ size=1, mtime=1.0)
+ refused = UnreadFile(path="/srv/music/b/two.flac", root="music",
+ reason="Permission denied", size=1, mtime=1.0)
+ indexer = _indexer(IndexProgress(), unread=[silent, refused],
+ stalled={"music": "/srv/music/a/three.flac"},
+ slow=("/srv/music/a/four.flac", 23.7))
+ config = MagicMock()
+ config.groups = []
+ client = _ui_client({"config": config, "indexers": {"g" * 32: indexer}})
+
+ one = client.get(f"/api/groups/{'g' * 32}/index-status").json()
+ assert one["unread"] == [
+ {"root": "music", "path": "/srv/music/a/one.flac", "reason": "no_answer"},
+ {"root": "music", "path": "/srv/music/b/two.flac", "reason": "Permission denied"}]
+ assert one["unread_total"] == 2
+ assert one["stalled"] == [{"root": "music", "path": "/srv/music/a/three.flac"}]
+
+ (band,) = client.get("/api/index-status").json()["groups"]
+ assert (band["slow_path"], band["slow_secs"]) == ("/srv/music/a/four.flac", 23)
+ assert (band["unread"], band["stalled"]) == (2, ["music"])
+
+
# ── /api/index-status (loopback, every group) ───────────────────────────────
def test_every_group_is_described_including_one_still_being_attached():
"""The band reads one route for the whole node. A group in its initial scan
is in state["indexers"] and not yet in groups_ctx, and must be there."""
- busy, idle = MagicMock(), MagicMock()
- busy.progress = IndexProgress(
+ busy = _indexer(IndexProgress(
scanning=True, scanned_bytes=10, total_bytes=40, current_dir="2024",
root="results", root_pos=1, kind="scan", files_done=1, files_total=4,
- queued=["archive"])
- idle.progress = IndexProgress()
+ queued=["archive"]))
+ idle = _indexer(IndexProgress())
config = MagicMock()
named = MagicMock()
named.id, named.name = "a" * 32, "outputs"
@@ -112,6 +150,7 @@ def test_every_group_is_described_including_one_still_being_attached():
"kind": "scan", "root": "results", "current_dir": "2024",
"scanned_bytes": 10, "total_bytes": 40, "files_done": 1, "files_total": 4,
"queued": ["archive"],
+ "slow_path": "", "slow_secs": 0, "unread": 0, "stalled": [],
}
assert groups["b" * 32]["group_name"] == "b" * 8
assert groups["b" * 32]["scanning"] is False