Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: fix AllDebrid downloader tests #922

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/program/services/downloaders/alldebrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,4 +260,4 @@ def get_files_and_links(self, torrent_id: str) -> List[DebridFile]:

except Exception as e:
logger.error(f"Failed to get files for {torrent_id}: {e}")
raise
raise
171 changes: 76 additions & 95 deletions src/tests/test_alldebrid_downloader.py
Original file line number Diff line number Diff line change
@@ -1,136 +1,102 @@
import json

import pytest
from unittest.mock import patch

from program.services.downloaders import alldebrid
from program.services.downloaders.alldebrid import (
AllDebridDownloader,
add_torrent,
get_instant_availability,
get_status,
get_torrents,
)
from program.services.downloaders.models import (
VIDEO_EXTENSIONS,
DebridFile,
TorrentContainer,
TorrentInfo,
DownloadStatus,
)
from program.settings.manager import settings_manager as settings
from program.utils.request import HttpMethod


@pytest.fixture
def downloader(instant, upload, status, status_all, delete):
def downloader(user, upload, status, status_all, files, delete):
"""Instance of AllDebridDownloader with API calls mocked"""
# mock API calls
_get = alldebrid.get
def get(url, **params):
match url:

def execute(self, method: HttpMethod, endpoint: str, **kwargs) -> dict:
params = kwargs.get("params", {})
match endpoint:
case "user":
return {"data": { "user": { "isPremium": True, "premiumUntil": 1735514599, } } }
case "magnet/instant":
return instant(url, **params)
return user()["data"]
case "magnet/upload":
return upload(url, **params)
return upload(endpoint, **params)["data"]
case "magnet/delete":
return delete(url, **params)
return delete(endpoint, **params)["data"]
case "magnet/status":
if params.get("id", False):
return status(url, **params)
return status(endpoint, **params)["data"]
else:
return status_all(url, **params)
return status_all(endpoint, **params)["data"]
case "magnet/files":
return files(endpoint, **params)["data"]
case _:
raise Exception("unmatched api call")
alldebrid.get = get

alldebrid_settings = settings.settings.downloaders.all_debrid
alldebrid_settings.enabled = True
alldebrid_settings.api_key = "key"

downloader = AllDebridDownloader()
assert downloader.initialized
yield downloader

# tear down mock
alldebrid.get = get


## Downloader tests
def test_process_hashes(downloader):
hashes = downloader.process_hashes(["abc"], None, [False, True])
assert len(hashes) == 1
raise Exception("unmatched api call %s" % endpoint)

with patch.object(alldebrid.AllDebridRequestHandler, 'execute', execute):
alldebrid_settings = settings.settings.downloaders.all_debrid
alldebrid_settings.enabled = True
alldebrid_settings.api_key = "key"

def test_download_cached(downloader):
torrent_id = downloader.download_cached({"infohash": "abc"})
assert torrent_id == MAGNET_ID
downloader = AllDebridDownloader()
assert downloader.initialized
yield downloader


def test_get_torrent_names(downloader):
names = downloader.get_torrent_names(123)
assert names == ("Ubuntu 24.04", None)
## DownloaderBase tests
def test_validate(downloader):
assert downloader.validate() == True


## API parsing tests
def test_get_instant_availability(instant):
alldebrid.get = instant
infohashes = [UBUNTU]
availability = get_instant_availability(infohashes)
assert len(availability[0].get("files", [])) == 2
def test_get_instant_availability(downloader):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is currently failing due to bugs in the downloader, @dreulavelle has a fix in his branch

assert downloader.get_instant_availability(MAGNET, "movie") == TorrentContainer(
infohash=MAGNET,
files=[DebridFile.create(filename="", filesize_bytes=123, filetype="movie")],
)


def test_get_instant_availability_unavailable(instant_unavailable):
alldebrid.get = instant_unavailable
infohashes = [UBUNTU]
availability = get_instant_availability(infohashes)
assert availability[0]["hash"] == UBUNTU
def test_add_torrent(downloader):
assert downloader.add_torrent(MAGNET) == ID


def test_add_torrent(upload):
alldebrid.get = upload
torrent_id = add_torrent(UBUNTU)
assert torrent_id == 251993753
def test_select_files(downloader):
assert downloader.select_files(ID, [1, 2, 3]) is None


def test_add_torrent_cached(upload_ready):
alldebrid.get = upload_ready
torrent_id = add_torrent(UBUNTU)
assert torrent_id == 251993753
def test_get_torrent_info(downloader):
torrent_info = downloader.get_torrent_info(ID)
assert torrent_info.id == int(ID)
assert torrent_info.name == "Big Buck Bunny"
assert torrent_info.status == DownloadStatus.READY
assert torrent_info.bytes == 276445467
assert torrent_info.progress == 100


def test_get_status(status):
alldebrid.get = status
torrent_status = get_status(251993753)
assert torrent_status["filename"] == "Ubuntu 24.04"
def test_delete_torrent(downloader):
assert downloader.delete_torrent(ID) is None # TODO: assert that delete was called


def test_get_status_unfinished(status_downloading):
alldebrid.get = status_downloading
torrent_status = get_status(251993753)
assert torrent_status["status"] == "Downloading"
# MAGNET is the infohash of the torrent.
MAGNET = "dd8255ecdc7ca55fb0bbf81323d87062db1f6d1c"
# ID is AllDebrid's internal ID for this torrent.
ID = "264640947"


def test_get_torrents(status_all):
alldebrid.get = status_all
torrents = get_torrents()
assert torrents[0]["status"] == "Ready"


def test_delete(delete):
alldebrid.get = delete
delete(123)


# Example requests - taken from real API calls
UBUNTU = "3648baf850d5930510c1f172b534200ebb5496e6"
MAGNET_ID = "251993753"
@pytest.fixture
def instant():
"""GET /magnet/instant?magnets[0]=infohash (torrent available)"""
with open("src/tests/test_data/alldebrid_magnet_instant.json") as f:
def user():
"""GET /user"""
with open("src/tests/test_data/alldebrid_user.json") as f:
body = json.load(f)
return lambda url, **params: body
return lambda: body

@pytest.fixture
def instant_unavailable():
"""GET /magnet/instant?magnets[0]=infohash (torrent unavailable)"""
with open("src/tests/test_data/alldebrid_magnet_instant_unavailable.json") as f:
body = json.load(f)
return lambda url, **params: body

@pytest.fixture
def upload():
Expand All @@ -139,39 +105,54 @@ def upload():
body = json.load(f)
return lambda url, **params: body


@pytest.fixture
def upload_ready():
"""GET /magnet/upload?magnets[]=infohash (torrent ready)"""
with open("src/tests/test_data/alldebrid_magnet_upload_ready.json") as f:
body = json.load(f)
return lambda url, **params: body


@pytest.fixture
def status():
"""GET /magnet/status?id=123 (debrid links ready)"""
with open("src/tests/test_data/alldebrid_magnet_status_one_ready.json") as f:
body = json.load(f)
return lambda url, **params: body


@pytest.fixture
def status_downloading():
"""GET /magnet/status?id=123 (debrid links not ready yet)"""
with open("src/tests/test_data/alldebrid_magnet_status_one_downloading.json") as f:
body = json.load(f)
return lambda url, **params: body


@pytest.fixture
def status_all():
"""GET /magnet/status (gets a list of all links instead of a single object)"""
# The body is the same as a single item, but with all your magnets in a list.
with open("src/tests/test_data/alldebrid_magnet_status_one_ready.json") as f:
body = json.load(f)
return lambda url, **params: {"status": "success", "data": {"magnets": [body["data"]["magnets"]]}}
return lambda url, **params: {
"status": "success",
"data": {"magnets": [body["data"]["magnets"]]},
}


@pytest.fixture
def files():
"""GET /magnet/files?id[]=123 (gets files and links for a magnet)"""
with open("src/tests/test_data/alldebrid_magnet_files.json") as f:
body = json.load(f)
return lambda url, **params: body


@pytest.fixture
def delete():
"""GET /delete"""
"""GET /delete?id=123"""
with open("src/tests/test_data/alldebrid_magnet_delete.json") as f:
body = json.load(f)
return lambda url, **params: body

27 changes: 27 additions & 0 deletions src/tests/test_data/alldebrid_magnet_files.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"status": "success",
"data": {
"magnets": [
{
"id": "264640947",
"files": [
{
"n": "Big Buck Bunny.en.srt",
"s": 140,
"l": "https://alldebrid.com/f/some-hash"
},
{
"n": "Big Buck Bunny.mp4",
"s": 276134947,
"l": "https://alldebrid.com/f/some-other-hash"
},
{
"n": "poster.jpg",
"s": 310380,
"l": "https://alldebrid.com/f/some-different-hash"
}
]
}
]
}
}
16 changes: 0 additions & 16 deletions src/tests/test_data/alldebrid_magnet_instant.json

This file was deleted.

12 changes: 0 additions & 12 deletions src/tests/test_data/alldebrid_magnet_instant_unavailable.json

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"status": "success",
"data": {
"magnets": {
"id": 251993753,
"filename": "Ubuntu 24.04",
"size": 8869638144,
"hash": "3648baf850d5930510c1f172b534200ebb5496e6",
"id": 264640947,
"filename": "Big Buck Bunny",
"size": 276445467,
"hash": "dd8255ecdc7ca55fb0bbf81323d87062db1f6d1c",
"status": "Downloading",
"statusCode": 1,
"downloaded": 165063971,
Expand All @@ -16,7 +16,6 @@
"uploadSpeed": 0,
"uploadDate": 1727454272,
"completionDate": 0,
"links": [],
"type": "m",
"notified": false,
"version": 2
Expand Down
Loading