274 lines
9.4 KiB
Python
274 lines
9.4 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""
|
||
|
|
Тесты для app.py — изолированные, без внешних зависимостей.
|
||
|
|
Запуск: python3 -m unittest test_app -v
|
||
|
|
"""
|
||
|
|
import sys
|
||
|
|
import os
|
||
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||
|
|
|
||
|
|
import unittest
|
||
|
|
from app import (
|
||
|
|
extract_hash_from_result,
|
||
|
|
generate_clean_magnet,
|
||
|
|
parse_size_to_bytes,
|
||
|
|
parse_size,
|
||
|
|
extract_resolution,
|
||
|
|
extract_quality,
|
||
|
|
generate_search_variants,
|
||
|
|
score_torrent,
|
||
|
|
normalize_search_term,
|
||
|
|
is_movie_torrent,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
class TestExtractHash(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_direct_hash_field(self):
|
||
|
|
result = {"Hash": "08ada5a7a6183aae1e09d831df6748d566095a10"}
|
||
|
|
self.assertEqual(extract_hash_from_result(result), "08ADA5A7A6183AAE1E09D831DF6748D566095A10")
|
||
|
|
|
||
|
|
def test_hash_from_magnet(self):
|
||
|
|
result = {
|
||
|
|
"Hash": "",
|
||
|
|
"Magnet": "magnet:?xt=urn:btih:08ada5a7a6183aae1e09d831df6748d566095a10&dn=test"
|
||
|
|
}
|
||
|
|
self.assertEqual(extract_hash_from_result(result), "08ADA5A7A6183AAE1E09D831DF6748D566095A10")
|
||
|
|
|
||
|
|
def test_hash_from_info_hash(self):
|
||
|
|
result = {"InfoHash": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"}
|
||
|
|
self.assertEqual(
|
||
|
|
extract_hash_from_result(result),
|
||
|
|
"A1B2C3D4E5F6A7B8C9D0E1F2A3B4C5D6E7F8A9B0"
|
||
|
|
)
|
||
|
|
|
||
|
|
def test_empty_result(self):
|
||
|
|
self.assertEqual(extract_hash_from_result({}), "")
|
||
|
|
self.assertEqual(extract_hash_from_result({"Hash": ""}), "")
|
||
|
|
|
||
|
|
def test_hash_from_torrent_url_no_btih(self):
|
||
|
|
result = {"Torrent": "https://rutracker.org/forum/dl.php?t=123456"}
|
||
|
|
self.assertEqual(extract_hash_from_result(result), "")
|
||
|
|
|
||
|
|
def test_case_insensitive_hash(self):
|
||
|
|
result = {"Hash": "08ada5a7a6183aae1e09d831df6748d566095a10"}
|
||
|
|
self.assertEqual(extract_hash_from_result(result), "08ADA5A7A6183AAE1E09D831DF6748D566095A10")
|
||
|
|
|
||
|
|
def test_id_field_as_hash(self):
|
||
|
|
result = {"Id": "08ada5a7a6183aae1e09d831df6748d566095a10"}
|
||
|
|
self.assertEqual(extract_hash_from_result(result), "08ADA5A7A6183AAE1E09D831DF6748D566095A10")
|
||
|
|
|
||
|
|
def test_non_hash_id_field(self):
|
||
|
|
result = {"Id": "12345", "Hash": ""}
|
||
|
|
self.assertEqual(extract_hash_from_result(result), "")
|
||
|
|
|
||
|
|
def test_hash_from_lowercase_field(self):
|
||
|
|
result = {"hash": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"}
|
||
|
|
self.assertEqual(
|
||
|
|
extract_hash_from_result(result),
|
||
|
|
"A1B2C3D4E5F6A7B8C9D0E1F2A3B4C5D6E7F8A9B0"
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
class TestGenerateCleanMagnet(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_basic_magnet(self):
|
||
|
|
magnet = generate_clean_magnet("08ada5a7a6183aae1e09d831df6748d566095a10", "Test Movie")
|
||
|
|
self.assertTrue(magnet.startswith("magnet:?xt=urn:btih:08ada5a7a6183aae1e09d831df6748d566095a10"))
|
||
|
|
self.assertIn("&dn=Test%20Movie", magnet)
|
||
|
|
self.assertIn("&tr=udp://tracker.opentrackr.org:1337/announce", magnet)
|
||
|
|
self.assertIn("&tr=udp://tracker.openbittorrent.com:6969/announce", magnet)
|
||
|
|
|
||
|
|
def test_empty_hash(self):
|
||
|
|
self.assertEqual(generate_clean_magnet(""), "")
|
||
|
|
self.assertEqual(generate_clean_magnet(None), "")
|
||
|
|
|
||
|
|
def test_no_title(self):
|
||
|
|
magnet = generate_clean_magnet("08ada5a7a6183aae1e09d831df6748d566095a10")
|
||
|
|
self.assertTrue(magnet.startswith("magnet:?xt=urn:btih:"))
|
||
|
|
self.assertNotIn("&dn=", magnet)
|
||
|
|
|
||
|
|
def test_cyrillic_title(self):
|
||
|
|
magnet = generate_clean_magnet("a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0", "Терминатор 2")
|
||
|
|
self.assertIn("&dn=%D0%A2%D0%B5%D1%80%D0%BC%D0%B8%D0%BD%D0%B0%D1%82%D0%BE%D1%80%202", magnet)
|
||
|
|
|
||
|
|
def test_has_trackers(self):
|
||
|
|
magnet = generate_clean_magnet("a" * 40)
|
||
|
|
expected_trackers = [
|
||
|
|
"tracker.opentrackr.org",
|
||
|
|
"open.stealth.si",
|
||
|
|
"tracker.openbittorrent.com",
|
||
|
|
"tracker.tamersunion.org",
|
||
|
|
"exodus.desync.com",
|
||
|
|
"tracker.moeking.me",
|
||
|
|
]
|
||
|
|
for tracker in expected_trackers:
|
||
|
|
self.assertIn(tracker, magnet, f"Missing tracker: {tracker}")
|
||
|
|
|
||
|
|
def test_no_dead_trackers(self):
|
||
|
|
magnet = generate_clean_magnet("a" * 40)
|
||
|
|
self.assertNotIn("coppersurfer.tk", magnet)
|
||
|
|
self.assertNotIn("leechers-paradise.org", magnet)
|
||
|
|
|
||
|
|
|
||
|
|
class TestParseSize(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_gb(self):
|
||
|
|
bytes_size, readable = parse_size("25.3 GB")
|
||
|
|
self.assertEqual(bytes_size, int(25.3 * 1024**3))
|
||
|
|
self.assertEqual(readable, "25.3 GB")
|
||
|
|
|
||
|
|
def test_mb(self):
|
||
|
|
bytes_size, readable = parse_size("6.2 MB")
|
||
|
|
self.assertEqual(bytes_size, int(6.2 * 1024**2))
|
||
|
|
|
||
|
|
def test_kb(self):
|
||
|
|
bytes_size, readable = parse_size("512 KB")
|
||
|
|
self.assertEqual(bytes_size, 512 * 1024)
|
||
|
|
|
||
|
|
def test_empty(self):
|
||
|
|
bytes_size, readable = parse_size("")
|
||
|
|
self.assertEqual(bytes_size, 0)
|
||
|
|
self.assertEqual(readable, "Неизвестно")
|
||
|
|
|
||
|
|
def test_none(self):
|
||
|
|
bytes_size, readable = parse_size(None)
|
||
|
|
self.assertEqual(bytes_size, 0)
|
||
|
|
self.assertEqual(readable, "Неизвестно")
|
||
|
|
|
||
|
|
|
||
|
|
class TestParseSizeToBytes(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_gb(self):
|
||
|
|
result = parse_size_to_bytes("25.3 GB")
|
||
|
|
self.assertAlmostEqual(result, 25.3 * 1024**3, delta=1)
|
||
|
|
|
||
|
|
def test_mb(self):
|
||
|
|
result = parse_size_to_bytes("500 MB")
|
||
|
|
self.assertEqual(result, 500 * 1024**2)
|
||
|
|
|
||
|
|
def test_empty(self):
|
||
|
|
self.assertEqual(parse_size_to_bytes(""), 0)
|
||
|
|
|
||
|
|
|
||
|
|
class TestExtractResolution(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_2160p(self):
|
||
|
|
self.assertEqual(extract_resolution("Movie 2024 UHD 2160p BluRay"), "2160p")
|
||
|
|
|
||
|
|
def test_4k(self):
|
||
|
|
self.assertEqual(extract_resolution("Movie 2024 4K HDR"), "2160p")
|
||
|
|
|
||
|
|
def test_1080p(self):
|
||
|
|
self.assertEqual(extract_resolution("Movie 2024 1080p WEB-DL"), "1080p")
|
||
|
|
|
||
|
|
def test_720p(self):
|
||
|
|
self.assertEqual(extract_resolution("Movie 2024 720p HDTV"), "720p")
|
||
|
|
|
||
|
|
def test_unknown(self):
|
||
|
|
self.assertEqual(extract_resolution("Movie Unknown Quality"), "Неизвестно")
|
||
|
|
|
||
|
|
|
||
|
|
class TestExtractQuality(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_bluray(self):
|
||
|
|
self.assertEqual(extract_quality("Movie 2024 Bluray 1080p"), "BluRay")
|
||
|
|
|
||
|
|
def test_bdrip(self):
|
||
|
|
self.assertEqual(extract_quality("Movie 2024 BDRip 720p"), "BluRay")
|
||
|
|
|
||
|
|
def test_webdl(self):
|
||
|
|
self.assertEqual(extract_quality("Movie 2024 WEB-DL 1080p"), "WEB-DL")
|
||
|
|
|
||
|
|
def test_webrip(self):
|
||
|
|
self.assertEqual(extract_quality("Movie 2024 WEBRip 720p"), "WEBRip")
|
||
|
|
|
||
|
|
def test_hdtv(self):
|
||
|
|
self.assertEqual(extract_quality("Movie 2024 HDTV 720p"), "HDTV")
|
||
|
|
|
||
|
|
def test_unknown(self):
|
||
|
|
self.assertEqual(extract_quality("Movie 2024 Some Quality"), "Unknown")
|
||
|
|
|
||
|
|
|
||
|
|
class TestNormalizeSearchTerm(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_basic(self):
|
||
|
|
self.assertEqual(normalize_search_term("The Terminator"), "Terminator")
|
||
|
|
|
||
|
|
def test_with_articles(self):
|
||
|
|
self.assertEqual(normalize_search_term("The Matrix Revolutions"), "Matrix.Revolutions")
|
||
|
|
|
||
|
|
def test_empty(self):
|
||
|
|
self.assertEqual(normalize_search_term(""), "")
|
||
|
|
self.assertEqual(normalize_search_term(None), "")
|
||
|
|
|
||
|
|
def test_spaces_to_dots(self):
|
||
|
|
self.assertEqual(normalize_search_term("Harry Potter"), "Harry.Potter")
|
||
|
|
|
||
|
|
|
||
|
|
class TestGenerateSearchVariants(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_basic(self):
|
||
|
|
variants = generate_search_variants("Terminator", "The Terminator", "1984")
|
||
|
|
self.assertIn("Terminator", variants)
|
||
|
|
self.assertIn("The Terminator", variants)
|
||
|
|
self.assertIn("Terminator 1984", variants)
|
||
|
|
|
||
|
|
def test_terminator_special(self):
|
||
|
|
variants = generate_search_variants("Терминатор 2", "Terminator 2", "1991")
|
||
|
|
self.assertIn("T2", variants)
|
||
|
|
self.assertIn("T2.Judgment.Day", variants)
|
||
|
|
|
||
|
|
def test_no_duplicates(self):
|
||
|
|
variants = generate_search_variants("Terminator", "Terminator", "1984")
|
||
|
|
self.assertEqual(len(variants), len(set(variants)))
|
||
|
|
|
||
|
|
|
||
|
|
class TestScoreTorrent(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_high_score_exact_match(self):
|
||
|
|
torrent = {
|
||
|
|
"title": "The Terminator 1984 1080p BluRay",
|
||
|
|
"quality": "BluRay",
|
||
|
|
"resolution": "1080p",
|
||
|
|
"seeds": 150,
|
||
|
|
}
|
||
|
|
score = score_torrent(torrent, "Terminator", "The Terminator", "1984")
|
||
|
|
self.assertGreater(score, 0.8)
|
||
|
|
|
||
|
|
def test_low_score_no_match(self):
|
||
|
|
torrent = {
|
||
|
|
"title": "Some Other Movie 2023 720p WEB-DL",
|
||
|
|
"quality": "WEB-DL",
|
||
|
|
"resolution": "720p",
|
||
|
|
"seeds": 5,
|
||
|
|
}
|
||
|
|
score = score_torrent(torrent, "Terminator", "The Terminator", "1984")
|
||
|
|
self.assertAlmostEqual(score, 0.3)
|
||
|
|
|
||
|
|
def test_score_capped_at_one(self):
|
||
|
|
torrent = {
|
||
|
|
"title": "The Terminator 1984 2160p BluRay",
|
||
|
|
"quality": "BluRay",
|
||
|
|
"resolution": "2160p",
|
||
|
|
"seeds": 200,
|
||
|
|
}
|
||
|
|
score = score_torrent(torrent, "The Terminator", "The Terminator", "1984")
|
||
|
|
self.assertLessEqual(score, 1.0)
|
||
|
|
|
||
|
|
|
||
|
|
class TestIsMovieTorrent(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_is_movie(self):
|
||
|
|
self.assertTrue(is_movie_torrent("The Terminator 1984 BluRay", "Terminator", "The Terminator"))
|
||
|
|
|
||
|
|
def test_not_movie_excluded_keyword(self):
|
||
|
|
self.assertFalse(is_movie_torrent("The Game 1997 1080p BluRay", "The Game", ""))
|
||
|
|
|
||
|
|
def test_not_movie_unknown_title(self):
|
||
|
|
self.assertFalse(is_movie_torrent("Some Other Movie 2023 720p", "Terminator", "The Terminator"))
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
unittest.main()
|