torrent-audit: make more robust
This commit is contained in:
@@ -53,6 +53,10 @@ let
|
||||
SINGLE8_NEW = "A" * 38 + "0D" # movieId=8, newer import → keeper (not in qBit)
|
||||
QUEUED_MOV = "A" * 38 + "0E" # in Radarr queue, not in history
|
||||
INPROGRESS_MOV = "A" * 38 + "0F" # movieId=10, older import, currently re-downloading
|
||||
KEEPER_GONE_OLD = "A" * 38 + "11" # movieId=11, older import, keeper incomplete in qBit
|
||||
KEEPER_GONE_NEW = "A" * 38 + "12" # movieId=11, newer import (keeper), incomplete in qBit
|
||||
INPROGRESS_MOV_NEW = "A" * 38 + "10" # movieId=10, newer import (not in qBit)
|
||||
|
||||
|
||||
# TV
|
||||
UNMANAGED_TV = "B" * 38 + "01"
|
||||
@@ -65,7 +69,9 @@ let
|
||||
REMOVED_TV_NEW = "B" * 38 + "08" # episodeId=400, newer import (not in qBit)
|
||||
INPROGRESS_TV = "B" * 38 + "09" # episodeId=500, older import, currently re-downloading
|
||||
INPROGRESS_TV_NEW = "B" * 38 + "0A" # episodeId=500, newer import (not in qBit)
|
||||
INPROGRESS_MOV_NEW = "A" * 38 + "10" # movieId=10, newer import (not in qBit)
|
||||
KEEPER_GONE_TV = "B" * 38 + "0B" # episodeId=600, older import, keeper incomplete in qBit
|
||||
KEEPER_GONE_TV_NEW = "B" * 38 + "0C" # episodeId=600, newer import (active), incomplete in qBit
|
||||
|
||||
|
||||
def make_torrent(h, name, size, added_on, state="uploading", progress=1.0):
|
||||
return {
|
||||
@@ -92,6 +98,10 @@ let
|
||||
# In-progress re-download: hash matches an old import, but data is
|
||||
# not yet on disk. Must NOT be flagged as abandoned (regression).
|
||||
make_torrent(INPROGRESS_MOV, "InProgress.Movie.2024", 8_000_000_000, 1704067209, state="downloading", progress=0.05),
|
||||
# Keeper-incomplete regression: old torrent is complete, keeper is
|
||||
# incomplete in qBittorrent. Must be REVIEW, not SAFE.
|
||||
make_torrent(KEEPER_GONE_OLD, "KeeperGone.Movie.2024", 2_000_000_000, 1704067210),
|
||||
make_torrent(KEEPER_GONE_NEW, "KeeperGone.Movie.2024.Upgr", 3_000_000_000, 1704067211, state="downloading", progress=0.10),
|
||||
],
|
||||
"tvshows": [
|
||||
make_torrent(UNMANAGED_TV, "Unmanaged.Show.S01E01", 1_000_000_000, 1704067200),
|
||||
@@ -101,6 +111,9 @@ let
|
||||
make_torrent(SEASON_PACK, "Season.Pack.S02", 5_000_000_000, 1704067204),
|
||||
make_torrent(REMOVED_TV, "Removed.Show.S01E01", 900_000_000, 1704067205),
|
||||
make_torrent(INPROGRESS_TV, "InProgress.Show.S01E01", 1_500_000_000, 1704067209, state="downloading", progress=0.05),
|
||||
# Keeper-incomplete regression for TV
|
||||
make_torrent(KEEPER_GONE_TV, "KeeperGone.Show.S01E01", 500_000_000, 1704067210),
|
||||
make_torrent(KEEPER_GONE_TV_NEW, "KeeperGone.Show.S01E01.Upgr", 800_000_000, 1704067211, state="downloading", progress=0.10),
|
||||
],
|
||||
}
|
||||
|
||||
@@ -127,6 +140,10 @@ let
|
||||
# In-progress re-download regression case for movies
|
||||
{"movieId": 10, "downloadId": INPROGRESS_MOV, "eventType": "downloadFolderImported", "date": "2024-01-01T00:00:00Z"},
|
||||
{"movieId": 10, "downloadId": INPROGRESS_MOV_NEW,"eventType": "downloadFolderImported", "date": "2024-06-01T00:00:00Z"},
|
||||
# Keeper-incomplete regression: old import + newer import (keeper) that
|
||||
# is incomplete in qBittorrent. The old torrent must be REVIEW.
|
||||
{"movieId": 11, "downloadId": KEEPER_GONE_OLD, "eventType": "downloadFolderImported", "date": "2024-01-01T00:00:00Z"},
|
||||
{"movieId": 11, "downloadId": KEEPER_GONE_NEW, "eventType": "downloadFolderImported", "date": "2024-06-01T00:00:00Z"},
|
||||
]
|
||||
|
||||
RADARR_MOVIES = [
|
||||
@@ -139,6 +156,7 @@ let
|
||||
{"id": 7, "hasFile": True, "movieFile": {"size": 4_000_000_000, "quality": {"quality": {"name": "Bluray-1080p"}}}},
|
||||
{"id": 8, "hasFile": True, "movieFile": {"size": 5_000_000_000, "quality": {"quality": {"name": "Remux-1080p"}}}},
|
||||
{"id": 10, "hasFile": True, "movieFile": {"size": 8_000_000_000, "quality": {"quality": {"name": "Remux-2160p"}}}},
|
||||
{"id": 11, "hasFile": True, "movieFile": {"size": 3_000_000_000, "quality": {"quality": {"name": "Remux-1080p"}}}},
|
||||
]
|
||||
|
||||
# ── Sonarr mock data ──────────────────────────────────────────────────
|
||||
@@ -164,6 +182,9 @@ let
|
||||
# In-progress re-download regression case for TV
|
||||
{"episodeId": 500, "seriesId": 1, "downloadId": INPROGRESS_TV, "eventType": "downloadFolderImported", "date": "2024-01-01T00:00:00Z"},
|
||||
{"episodeId": 500, "seriesId": 1, "downloadId": INPROGRESS_TV_NEW,"eventType": "downloadFolderImported", "date": "2024-06-01T00:00:00Z"},
|
||||
# Keeper-incomplete regression for TV
|
||||
{"episodeId": 600, "seriesId": 1, "downloadId": KEEPER_GONE_TV, "eventType": "downloadFolderImported", "date": "2024-01-01T00:00:00Z"},
|
||||
{"episodeId": 600, "seriesId": 1, "downloadId": KEEPER_GONE_TV_NEW,"eventType": "downloadFolderImported", "date": "2024-06-01T00:00:00Z"},
|
||||
]
|
||||
SONARR_HISTORY_ALL = SONARR_HISTORY_PAGE1 + SONARR_HISTORY_PAGE2
|
||||
|
||||
@@ -335,14 +356,14 @@ pkgs.testers.runNixOSTest {
|
||||
with subtest("Detects unmanaged movie torrent"):
|
||||
assert "Unmanaged.Movie.2024" in unmanaged_section, \
|
||||
"Should detect unmanaged movie"
|
||||
assert "1 unmanaged / 10 total" in unmanaged_section, \
|
||||
"Should show 1 unmanaged movie out of 10"
|
||||
assert "1 unmanaged / 12 total" in unmanaged_section, \
|
||||
"Should show 1 unmanaged movie out of 12"
|
||||
|
||||
with subtest("Detects unmanaged TV torrent"):
|
||||
assert "Unmanaged.Show.S01E01" in unmanaged_section, \
|
||||
"Should detect unmanaged TV show"
|
||||
assert "1 unmanaged / 7 total" in unmanaged_section, \
|
||||
"Should show 1 unmanaged TV show out of 7"
|
||||
assert "1 unmanaged / 9 total" in unmanaged_section, \
|
||||
"Should show 1 unmanaged TV show out of 9"
|
||||
|
||||
with subtest("Empty category shows zero counts"):
|
||||
assert "0 unmanaged / 0 total" in unmanaged_section, \
|
||||
@@ -434,15 +455,42 @@ pkgs.testers.runNixOSTest {
|
||||
break
|
||||
|
||||
with subtest("Correct abandoned counts per category"):
|
||||
assert "movies (3 abandoned)" in abandoned_section, \
|
||||
"Should show 3 abandoned movies"
|
||||
assert "tvshows (2 abandoned)" in abandoned_section, \
|
||||
"Should show 2 abandoned TV shows"
|
||||
assert "movies (4 abandoned)" in abandoned_section, \
|
||||
"Should show 4 abandoned movies"
|
||||
assert "tvshows (3 abandoned)" in abandoned_section, \
|
||||
"Should show 3 abandoned TV shows"
|
||||
|
||||
with subtest("Correct summary totals"):
|
||||
assert "ABANDONED: 5 total (2 safe to delete)" in output, \
|
||||
"Summary should show 5 total abandoned, 2 safe to delete"
|
||||
assert "ABANDONED: 7 total (2 safe to delete)" in output, \
|
||||
"Summary should show 7 total abandoned, 2 safe to delete"
|
||||
assert "SAFE TO RECLAIM: 3.4 GiB" in output, \
|
||||
"Should report 3.4 GiB reclaimable (2.8 GiB movie + 0.7 GiB TV)"
|
||||
|
||||
with subtest("Keeper-incomplete movie triggers REVIEW"):
|
||||
assert "KeeperGone.Movie.2024" in abandoned_section, \
|
||||
"Should detect abandoned torrent with incomplete keeper"
|
||||
assert_note_near(abandoned_section, "KeeperGone.Movie.2024", "keeper torrent incomplete")
|
||||
for line in abandoned_section.splitlines():
|
||||
if "KeeperGone.Movie.2024" in line:
|
||||
assert "REVIEW" in line, f"Keeper-incomplete movie should be REVIEW, got: {line}"
|
||||
break
|
||||
|
||||
with subtest("Keeper-incomplete TV triggers REVIEW"):
|
||||
assert "KeeperGone.Show.S01E01" in abandoned_section, \
|
||||
"Should detect abandoned TV torrent with incomplete keeper"
|
||||
assert_note_near(abandoned_section, "KeeperGone.Show.S01E01", "replacement torrent incomplete")
|
||||
for line in abandoned_section.splitlines():
|
||||
if "KeeperGone.Show.S01E01" in line:
|
||||
assert "REVIEW" in line, f"Keeper-incomplete TV should be REVIEW, got: {line}"
|
||||
break
|
||||
|
||||
with subtest("Keeper-incomplete does not affect existing SAFE verdicts"):
|
||||
for line in abandoned_section.splitlines():
|
||||
if "Old.Movie.Quality.2024" in line:
|
||||
assert "SAFE" in line, f"Old movie should still be SAFE, got: {line}"
|
||||
break
|
||||
for line in abandoned_section.splitlines():
|
||||
if "Old.Show.S01E01" in line:
|
||||
assert "SAFE" in line, f"Old TV should still be SAFE, got: {line}"
|
||||
break
|
||||
'';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user