diff --git a/src/tribler/test_unit/base_restapi.py b/src/tribler/test_unit/base_restapi.py deleted file mode 100644 index 74e2c6c2ae..0000000000 --- a/src/tribler/test_unit/base_restapi.py +++ /dev/null @@ -1,103 +0,0 @@ -from __future__ import annotations - -import asyncio -from asyncio import StreamReader, get_running_loop -from io import BytesIO -from json import loads -from typing import TYPE_CHECKING, Any - -from aiohttp import HttpVersion -from aiohttp.abc import AbstractStreamWriter -from aiohttp.http_parser import RawRequestMessage -from aiohttp.web_request import Request -from multidict import CIMultiDict, CIMultiDictProxy, MultiDict, MultiDictProxy -from yarl import URL - -if TYPE_CHECKING: - from tribler.core.restapi.rest_endpoint import RESTResponse - - -class BodyCapture(BytesIO, AbstractStreamWriter): - """ - Helper-class to capture RESTResponse bodies. - """ - - async def write(self, value: bytes) -> None: - """ - Write to our Bytes stream. - """ - BytesIO.write(self, value) - - -class MockRequest(Request): - """ - Base class for mocked REST requests. - """ - - class Transport: - """ - A fake transport that does nothing. - """ - - def __init__(self) -> None: - """ - Create a new fake Transport. - """ - super().__init__() - self.closing = False - - def get_extra_info(self, _: str) -> None: - """ - Get extra info, which is always None. - """ - return - - def is_closing(self) -> bool: - """ - Get the closing state. - """ - return self.closing - - def __init__(self, query: dict, method: str = "GET", path: str = "", - payload_writer: AbstractStreamWriter | None = None) -> None: - """ - Create a new MockRequest, just like if it were returned from aiohttp. - """ - message = RawRequestMessage(method, path, HttpVersion(1, 0), CIMultiDictProxy(CIMultiDict({})), - ((b'', b''),), True, None, False, False, URL(path)) - self._transport = MockRequest.Transport() - super().__init__(message=message, payload=StreamReader(), protocol=self, - payload_writer=payload_writer, task=None, loop=get_running_loop()) - self._query = query - - @property - def query(self) -> MultiDictProxy[str]: - """ - Overwrite the query with the query passed in our constructor. - """ - return MultiDictProxy(MultiDict(self._query)) - - @property - def transport(self) -> asyncio.Transport | None: - """ - Overwrite the transport with our fake transport. - """ - return self._transport - - -async def response_to_bytes(response: RESTResponse) -> bytes: - """ - Get the bytes of a RESTResponse's body. - """ - capture = BodyCapture() - if isinstance(response.body, bytes): - return response.body - await response.body.write(capture) - return capture.getvalue() - - -async def response_to_json(response: RESTResponse) -> Any: # noqa: ANN401 - """ - Get the JSON dict of a RESTResponse's body. - """ - return loads(await response_to_bytes(response)) diff --git a/src/tribler/test_unit/core/content_discovery/restapi/test_search_endpoint.py b/src/tribler/test_unit/core/content_discovery/restapi/test_search_endpoint.py index 5524328e81..76f90247ad 100644 --- a/src/tribler/test_unit/core/content_discovery/restapi/test_search_endpoint.py +++ b/src/tribler/test_unit/core/content_discovery/restapi/test_search_endpoint.py @@ -7,11 +7,11 @@ from ipv8.peerdiscovery.network import Network from ipv8.test.base import TestBase from ipv8.test.mocking.endpoint import AutoMockEndpoint +from ipv8.test.REST.rest_base import MockRequest, response_to_json from tribler.core.content_discovery.community import ContentDiscoveryCommunity from tribler.core.content_discovery.restapi.search_endpoint import SearchEndpoint from tribler.core.restapi.rest_endpoint import HTTP_BAD_REQUEST -from tribler.test_unit.base_restapi import MockRequest, response_to_json class MockContentDiscoveryCommunity(ContentDiscoveryCommunity): @@ -33,19 +33,6 @@ def send_search_request(self, **kwargs) -> tuple[UUID, list[Peer]]: return UUID(int=1), [self.my_peer] -class SearchRequest(MockRequest): - """ - A MockRequest that mimics SearchRequests. - """ - - def __init__(self, query: dict) -> None: - """ - Create a new SearchRequest. - """ - super().__init__(query, "PUT", "/search/remote") - self.context = [MockContentDiscoveryCommunity()] - - class TestSearchEndpoint(TestBase): """ Tests for the SearchEndpoint REST endpoint. @@ -56,8 +43,10 @@ async def test_remote_search_bad_request(self) -> None: Test if a bad request returns the bad request status. """ endpoint = SearchEndpoint() + request = MockRequest("/api/search/remote", "PUT", {"channel_pk": "GG"}) + request.context = [MockContentDiscoveryCommunity()] - response = await endpoint.remote_search(SearchRequest({"channel_pk": "GG"})) + response = await endpoint.remote_search(request) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -66,8 +55,10 @@ async def test_remote_search(self) -> None: Test if a good search request returns a dict with the UUID and serving peers. """ endpoint = SearchEndpoint() + request = MockRequest("/api/search/remote", "PUT", {"channel_pk": "AA", "fts_text": ""}) + request.context = [MockContentDiscoveryCommunity()] - response = await endpoint.remote_search(SearchRequest({"channel_pk": "AA", "fts_text": ""})) + response = await endpoint.remote_search(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) diff --git a/src/tribler/test_unit/core/database/restapi/test_database_endpoint.py b/src/tribler/test_unit/core/database/restapi/test_database_endpoint.py index ef05bdf759..2a76d380fd 100644 --- a/src/tribler/test_unit/core/database/restapi/test_database_endpoint.py +++ b/src/tribler/test_unit/core/database/restapi/test_database_endpoint.py @@ -1,83 +1,17 @@ from __future__ import annotations from asyncio import sleep -from typing import TYPE_CHECKING, Callable +from typing import Callable from unittest.mock import AsyncMock, Mock, call -from aiohttp.web_urldispatcher import UrlMappingMatchInfo from ipv8.test.base import TestBase +from ipv8.test.REST.rest_base import MockRequest, response_to_json from multidict import MultiDict, MultiDictProxy from tribler.core.database.layers.knowledge import ResourceType, SimpleStatement from tribler.core.database.restapi.database_endpoint import DatabaseEndpoint, parse_bool from tribler.core.database.serialization import REGULAR_TORRENT from tribler.core.restapi.rest_endpoint import HTTP_BAD_REQUEST -from tribler.test_unit.base_restapi import MockRequest, response_to_json - -if TYPE_CHECKING: - from tribler.core.database.store import MetadataStore - - -class TorrentHealthRequest(MockRequest): - """ - A MockRequest that mimics TorrentHealthRequests. - """ - - def __init__(self, query: dict, infohash: str, mds: MetadataStore | None) -> None: - """ - Create a new TorrentHealthRequest. - """ - super().__init__(query, "GET", f"/metadata/torrents/{infohash}/health") - self._infohash = infohash - self.context = (mds,) - - @property - def match_info(self) -> UrlMappingMatchInfo: - """ - Get the match info (the infohash in the url). - """ - return UrlMappingMatchInfo({"infohash": self._infohash}, Mock()) - - -class PopularTorrentsRequest(MockRequest): - """ - A MockRequest that mimics PopularTorrentsRequests. - """ - - def __init__(self, query: dict, mds: MetadataStore | None) -> None: - """ - Create a new PopularTorrentsRequest. - """ - super().__init__(query, "GET", "/metadata/torrents/popular") - self.context = (mds,) - - -class SearchLocalRequest(MockRequest): - """ - A MockRequest that mimics SearchLocalRequests. - """ - - def __init__(self, query: dict, mds: MetadataStore | None) -> None: - """ - Create a new SearchLocalRequest. - """ - default_query = {"fts_text": ""} - default_query.update(query) - super().__init__(default_query, "GET", "/metadata/search/local") - self.context = (mds,) - - -class SearchCompletionsRequest(MockRequest): - """ - A MockRequest that mimics SearchCompletionsRequests. - """ - - def __init__(self, query: dict, mds: MetadataStore | None) -> None: - """ - Create a new SearchCompletionsRequest. - """ - super().__init__(query, "GET", "/metadata/search/completions") - self.context = (mds, ) class TestDatabaseEndpoint(TestBase): @@ -144,8 +78,10 @@ async def test_get_torrent_health_bad_timeout(self) -> None: Test if a bad timeout value in get_torrent_health leads to a HTTP_BAD_REQUEST status. """ endpoint = DatabaseEndpoint() + request = MockRequest("/metadata/torrents/AA/health", query={"timeout": "AA"}, match_info={"infohash": "AA"}) + request.context = [endpoint.mds] - response = await endpoint.get_torrent_health(TorrentHealthRequest({"timeout": "AA"}, "AA", endpoint.mds)) + response = await endpoint.get_torrent_health(request) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -154,8 +90,10 @@ async def test_get_torrent_health_no_checker(self) -> None: Test if calling get_torrent_health without a torrent checker leads to a false checking status. """ endpoint = DatabaseEndpoint() + request = MockRequest("/metadata/torrents/AA/health", match_info={"infohash": "AA"}) + request.context = [endpoint.mds] - response = await endpoint.get_torrent_health(TorrentHealthRequest({}, "AA", endpoint.mds)) + response = await endpoint.get_torrent_health(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -168,8 +106,10 @@ async def test_get_torrent_health(self) -> None: endpoint = DatabaseEndpoint() check_torrent_health = AsyncMock() endpoint.torrent_checker = Mock(check_torrent_health=check_torrent_health) + request = MockRequest("/metadata/torrents/AA/health", match_info={"infohash": "AA"}) + request.context = [endpoint.mds] - response = await endpoint.get_torrent_health(TorrentHealthRequest({}, "AA", endpoint.mds)) + response = await endpoint.get_torrent_health(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -228,8 +168,10 @@ async def test_get_popular_torrents(self) -> None: tdef=Mock(infohash="AA")) endpoint.download_manager = Mock(get_download=Mock(return_value=download), metainfo_requests=[]) endpoint.mds = Mock(get_entries=Mock(return_value=[Mock(to_simple_dict=Mock(return_value=metadata))])) + request = MockRequest("/api/metadata/torrents/popular") + request.context = [endpoint.mds] - response = await endpoint.get_popular_torrents(PopularTorrentsRequest(metadata, endpoint.mds)) + response = await endpoint.get_popular_torrents(request) response_body_json = await response_to_json(response) response_results = response_body_json["results"][0] @@ -249,8 +191,10 @@ async def test_local_search_bad_query(self) -> None: Test if a bad value leads to a bad request status. """ endpoint = DatabaseEndpoint() + request = MockRequest("/api/metadata/search/local", query={"fts_text": "", "first": "bla"}) + request.context = [endpoint.mds] - response = await endpoint.local_search(SearchLocalRequest({"first": "bla"}, endpoint.mds)) + response = await endpoint.local_search(request) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -262,8 +206,10 @@ async def test_local_search_errored_search(self) -> None: """ endpoint = DatabaseEndpoint() endpoint.tribler_db = Mock() + request = MockRequest("/api/metadata/search/local", query={"fts_text": ""}) + request.context = [endpoint.mds] - response = await endpoint.local_search(SearchLocalRequest({}, endpoint.mds)) + response = await endpoint.local_search(request) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -276,8 +222,10 @@ async def test_local_search_no_knowledge(self) -> None: endpoint.mds = Mock(run_threaded=self.mds_run_now, get_total_count=Mock(), get_max_rowid=Mock(), get_entries=Mock(return_value=[Mock(to_simple_dict=Mock(return_value={"test": "test", "type": -1}))])) + request = MockRequest("/api/metadata/search/local", query={"fts_text": ""}) + request.context = [endpoint.mds] - response = await endpoint.local_search(SearchLocalRequest({}, endpoint.mds)) + response = await endpoint.local_search(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -297,8 +245,11 @@ async def test_local_search_no_knowledge_include_total(self) -> None: get_max_rowid=Mock(return_value=7), get_entries=Mock(return_value=[Mock(to_simple_dict=Mock(return_value={"test": "test", "type": -1}))])) + request = MockRequest("/api/metadata/search/local", query={"fts_text": "", + "include_total": "I would like this"}) + request.context = [endpoint.mds] - response = await endpoint.local_search(SearchLocalRequest({"include_total": "I would like this"}, endpoint.mds)) + response = await endpoint.local_search(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -315,8 +266,10 @@ async def test_completions_bad_query(self) -> None: Test if a missing query leads to a bad request status. """ endpoint = DatabaseEndpoint() + request = MockRequest("/api/metadata/search/completions") + request.context = [endpoint.mds] - response = await endpoint.completions(SearchCompletionsRequest({}, endpoint.mds)) + response = await endpoint.completions(request) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -326,8 +279,10 @@ async def test_completions_lowercase_search(self) -> None: """ endpoint = DatabaseEndpoint() endpoint.mds = Mock(get_auto_complete_terms=Mock(return_value=["test1", "test2"])) + request = MockRequest("/api/metadata/search/completions", query={"q": "test"}) + request.context = [endpoint.mds] - response = await endpoint.completions(SearchCompletionsRequest({"q": "test"}, endpoint.mds)) + response = await endpoint.completions(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -340,8 +295,10 @@ async def test_completions_mixed_case_search(self) -> None: """ endpoint = DatabaseEndpoint() endpoint.mds = Mock(get_auto_complete_terms=Mock(return_value=["test1", "test2"])) + request = MockRequest("/api/metadata/search/completions", query={"q": "TeSt"}) + request.context = [endpoint.mds] - response = await endpoint.completions(SearchCompletionsRequest({"q": "TeSt"}, endpoint.mds)) + response = await endpoint.completions(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) diff --git a/src/tribler/test_unit/core/knowledge/restapi/test_knowledge_endpoint.py b/src/tribler/test_unit/core/knowledge/restapi/test_knowledge_endpoint.py index c70e1ec714..12f85fb115 100644 --- a/src/tribler/test_unit/core/knowledge/restapi/test_knowledge_endpoint.py +++ b/src/tribler/test_unit/core/knowledge/restapi/test_knowledge_endpoint.py @@ -1,18 +1,16 @@ from unittest.mock import Mock -from aiohttp.web_urldispatcher import UrlMappingMatchInfo from ipv8.keyvault.crypto import default_eccrypto from ipv8.peer import Peer from ipv8.peerdiscovery.network import Network from ipv8.test.base import TestBase from ipv8.test.mocking.endpoint import AutoMockEndpoint +from ipv8.test.REST.rest_base import MockRequest, response_to_json from tribler.core.database.layers.knowledge import ResourceType -from tribler.core.database.tribler_database import TriblerDatabase from tribler.core.knowledge.community import KnowledgeCommunity, KnowledgeCommunitySettings from tribler.core.knowledge.payload import StatementOperation from tribler.core.knowledge.restapi.knowledge_endpoint import KnowledgeEndpoint -from tribler.test_unit.base_restapi import MockRequest, response_to_json class MockCommunity(KnowledgeCommunity): @@ -36,54 +34,6 @@ def sign(self, operation: StatementOperation) -> bytes: return b"" -class UpdateKnowledgeEntriesRequest(MockRequest): - """ - A MockRequest that mimics UpdateKnowledgeEntriesRequests. - """ - - def __init__(self, query: dict, infohash: str, db: TriblerDatabase) -> None: - """ - Create a new UpdateKnowledgeEntriesRequest. - """ - super().__init__(query, "PATCH", f"/knowledge/{infohash}") - self._infohash = infohash - self.context = [db] - - async def json(self) -> dict: - """ - Get the json equivalent of the query (i.e., just the query). - """ - return self._query - - @property - def match_info(self) -> UrlMappingMatchInfo: - """ - Get the match info (the infohash in the url). - """ - return UrlMappingMatchInfo({"infohash": self._infohash}, Mock()) - - -class GetTagSuggestionsRequest(MockRequest): - """ - A MockRequest that mimics GetTagSuggestionsRequests. - """ - - def __init__(self, infohash: str, db: TriblerDatabase) -> None: - """ - Create a new GetTagSuggestionsRequest. - """ - super().__init__({}, "GET", f"/knowledge/{infohash}/tag_suggestions") - self._infohash = infohash - self.context = [db] - - @property - def match_info(self) -> UrlMappingMatchInfo: - """ - Get the match info (the infohash in the url). - """ - return UrlMappingMatchInfo({"infohash": self._infohash}, Mock()) - - class TestKnowledgeEndpoint(TestBase): """ Tests for the KnowledgeEndpoint REST endpoint. @@ -117,9 +67,10 @@ async def test_add_tag_invalid_infohash(self) -> None: Test if an error is returned if we try to add a tag to content with an invalid infohash. """ post_data = {"knowledge": [self.tag_to_statement("abc"), self.tag_to_statement("def")]} + request = MockRequest("/api/knowledge/3f3", "PATCH", post_data, {"infohash": "3f3"}) + request.context = [self.endpoint.db] - response = await self.endpoint.update_knowledge_entries(UpdateKnowledgeEntriesRequest(post_data, "3f3", - self.endpoint.db)) + response = await self.endpoint.update_knowledge_entries(request) response_body_json = await response_to_json(response) self.assertEqual(400, response.status) @@ -130,9 +81,10 @@ async def test_add_invalid_tag_too_short(self) -> None: Test whether an error is returned if we try to add a tag that is too short or long. """ post_data = {"statements": [self.tag_to_statement("a")]} + request = MockRequest("/api/knowledge/" + "a" * 40, "PATCH", post_data, {"infohash": "a" * 40}) + request.context = [self.endpoint.db] - response = await self.endpoint.update_knowledge_entries(UpdateKnowledgeEntriesRequest(post_data, "a" * 40, - self.endpoint.db)) + response = await self.endpoint.update_knowledge_entries(request) response_body_json = await response_to_json(response) self.assertEqual(400, response.status) @@ -143,9 +95,10 @@ async def test_add_invalid_tag_too_long(self) -> None: Test whether an error is returned if we try to add a tag that is too short or long. """ post_data = {"statements": [self.tag_to_statement("a" * 60)]} + request = MockRequest("/api/knowledge/" + "a" * 40, "PATCH", post_data, {"infohash": "a" * 40}) + request.context = [self.endpoint.db] - response = await self.endpoint.update_knowledge_entries(UpdateKnowledgeEntriesRequest(post_data, "a" * 40, - self.endpoint.db)) + response = await self.endpoint.update_knowledge_entries(request) response_body_json = await response_to_json(response) self.assertEqual(400, response.status) @@ -158,9 +111,10 @@ async def test_modify_tags(self) -> None: post_data = {"statements": [self.tag_to_statement("abc"), self.tag_to_statement("def")]} self.endpoint.db.knowledge.get_statements = Mock(return_value=[]) self.endpoint.db.knowledge.get_clock = Mock(return_value=0) + request = MockRequest("/api/knowledge/" + "a" * 40, "PATCH", post_data, {"infohash": "a" * 40}) + request.context = [self.endpoint.db] - response = await self.endpoint.update_knowledge_entries(UpdateKnowledgeEntriesRequest(post_data, "a" * 40, - self.endpoint.db)) + response = await self.endpoint.update_knowledge_entries(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -174,9 +128,10 @@ async def test_modify_tags_no_community(self) -> None: post_data = {"statements": [self.tag_to_statement("abc"), self.tag_to_statement("def")]} self.endpoint.db.knowledge.get_statements = Mock(return_value=[]) self.endpoint.db.knowledge.get_clock = Mock(return_value=0) + request = MockRequest("/api/knowledge/" + "a" * 40, "PATCH", post_data, {"infohash": "a" * 40}) + request.context = [self.endpoint.db] - response = await self.endpoint.update_knowledge_entries(UpdateKnowledgeEntriesRequest(post_data, "a" * 40, - self.endpoint.db)) + response = await self.endpoint.update_knowledge_entries(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -186,7 +141,10 @@ async def test_get_suggestions_invalid_infohash(self) -> None: """ Test if an error is returned if we fetch suggestions from content with an invalid infohash. """ - response = await self.endpoint.get_tag_suggestions(GetTagSuggestionsRequest("3f3", self.endpoint.db)) + request = MockRequest("/api/knowledge/3f3/tag_suggestions", match_info={"infohash": "3f3"}) + request.context = [self.endpoint.db] + + response = await self.endpoint.get_tag_suggestions(request) response_body_json = await response_to_json(response) self.assertEqual(400, response.status) @@ -197,8 +155,10 @@ async def test_get_suggestions(self) -> None: Test if we can successfully fetch suggestions from content. """ self.endpoint.db.knowledge.get_suggestions = Mock(return_value=["test"]) + request = MockRequest("/api/knowledge/" + "a" * 40 + "/tag_suggestions", match_info={"infohash": "a" * 40}) + request.context = [self.endpoint.db] - response = await self.endpoint.get_tag_suggestions(GetTagSuggestionsRequest("a" * 40, self.endpoint.db)) + response = await self.endpoint.get_tag_suggestions(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) diff --git a/src/tribler/test_unit/core/libtorrent/download_manager/test_download_manager.py b/src/tribler/test_unit/core/libtorrent/download_manager/test_download_manager.py index de827d334a..568cae1c4c 100644 --- a/src/tribler/test_unit/core/libtorrent/download_manager/test_download_manager.py +++ b/src/tribler/test_unit/core/libtorrent/download_manager/test_download_manager.py @@ -19,6 +19,7 @@ from tribler.core.libtorrent.torrentdef import TorrentDef, TorrentDefNoMetainfo from tribler.core.notifier import Notifier from tribler.test_unit.core.libtorrent.mocks import TORRENT_WITH_DIRS_CONTENT +from tribler.test_unit.mocks import MockTriblerConfigManager class TestDownloadManager(TestBase): diff --git a/src/tribler/test_unit/core/libtorrent/restapi/test_create_torrent_endpoint.py b/src/tribler/test_unit/core/libtorrent/restapi/test_create_torrent_endpoint.py index b336f95440..3d33ea563a 100644 --- a/src/tribler/test_unit/core/libtorrent/restapi/test_create_torrent_endpoint.py +++ b/src/tribler/test_unit/core/libtorrent/restapi/test_create_torrent_endpoint.py @@ -5,34 +5,16 @@ from configobj import ConfigObj from ipv8.test.base import TestBase +from ipv8.test.REST.rest_base import MockRequest, response_to_json import tribler.core.libtorrent.restapi.create_torrent_endpoint as ep_module from tribler.core.libtorrent.download_manager.download_config import SPEC_CONTENT, DownloadConfig from tribler.core.libtorrent.restapi.create_torrent_endpoint import CreateTorrentEndpoint from tribler.core.restapi.rest_endpoint import HTTP_BAD_REQUEST, HTTP_INTERNAL_SERVER_ERROR -from tribler.test_unit.base_restapi import MockRequest, response_to_json from tribler.test_unit.core.libtorrent.mocks import TORRENT_WITH_DIRS_CONTENT from tribler.test_unit.mocks import MockTriblerConfigManager -class CreateTorrentRequest(MockRequest): - """ - A MockRequest that mimics CreateTorrentRequests. - """ - - def __init__(self, query: dict) -> None: - """ - Create a new CreateTorrentRequest. - """ - super().__init__(query, "POST", "/createtorrent") - - async def json(self) -> dict: - """ - Get the json equivalent of the query (i.e., just the query). - """ - return self._query - - class TestCreateTorrentEndpoint(TestBase): """ Tests for the CreateTorrentEndpoint class. @@ -51,7 +33,9 @@ async def test_no_files(self) -> None: """ Test if a request without files leads to a bad request status. """ - response = await self.endpoint.create_torrent(CreateTorrentRequest({})) + request = MockRequest("/api/createtorrent", "POST", {}) + + response = await self.endpoint.create_torrent(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -61,8 +45,10 @@ async def test_failure_oserror(self) -> None: """ Test if processing a request that leads to an OSError is gracefully reported. """ + request = MockRequest("/api/createtorrent", "POST", {"files": [str(Path(__file__))]}) + with patch.dict(ep_module.__dict__, {"create_torrent_file": Mock(side_effect=OSError("test"))}): - response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))]})) + response = await self.endpoint.create_torrent(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -73,9 +59,11 @@ async def test_failure_unicodedecodeerror(self) -> None: """ Test if processing a request that leads to an OSError is gracefully reported. """ + request = MockRequest("/api/createtorrent", "POST", {"files": [str(Path(__file__))]}) + with patch.dict(ep_module.__dict__, {"create_torrent_file": Mock(side_effect=UnicodeDecodeError("utf-8", b"", 0, 1, "𓀬"))}): - response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))]})) + response = await self.endpoint.create_torrent(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -87,8 +75,10 @@ async def test_failure_runtimeerror(self) -> None: """ Test if processing a request that leads to an RuntimeError is gracefully reported. """ + request = MockRequest("/api/createtorrent", "POST", {"files": [str(Path(__file__))]}) + with patch.dict(ep_module.__dict__, {"create_torrent_file": Mock(side_effect=RuntimeError("test"))}): - response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))]})) + response = await self.endpoint.create_torrent(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -99,9 +89,11 @@ async def test_create_default(self) -> None: """ Test if creating a torrent from defaults works. """ + request = MockRequest("/api/createtorrent", "POST", {"files": [str(Path(__file__))]}) mocked_create_torrent_file = Mock(return_value={"metainfo": TORRENT_WITH_DIRS_CONTENT}) + with patch.dict(ep_module.__dict__, {"create_torrent_file": mocked_create_torrent_file}): - response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))]})) + response = await self.endpoint.create_torrent(request) response_body_json = await response_to_json(response) _, call_params, __ = mocked_create_torrent_file.call_args.args @@ -117,10 +109,11 @@ async def test_create_with_comment(self) -> None: """ Test if creating a torrent with a custom comment works. """ + request = MockRequest("/api/createtorrent", "POST", {"files": [str(Path(__file__))], "description": "test"}) mocked_create_torrent_file = Mock(return_value={"metainfo": TORRENT_WITH_DIRS_CONTENT}) + with patch.dict(ep_module.__dict__, {"create_torrent_file": mocked_create_torrent_file}): - response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))], - "description": "test"})) + response = await self.endpoint.create_torrent(request) response_body_json = await response_to_json(response) _, call_params, __ = mocked_create_torrent_file.call_args.args @@ -133,12 +126,14 @@ async def test_create_with_trackers(self) -> None: """ Test if creating a torrent with custom trackers works. """ + request = MockRequest("/api/createtorrent", "POST",{ + "files": [str(Path(__file__))], + "trackers": ["http://127.0.0.1/announce", "http://10.0.0.2/announce"] + }) mocked_create_torrent_file = Mock(return_value={"metainfo": TORRENT_WITH_DIRS_CONTENT}) + with patch.dict(ep_module.__dict__, {"create_torrent_file": mocked_create_torrent_file}): - response = await self.endpoint.create_torrent(CreateTorrentRequest({ - "files": [str(Path(__file__))], - "trackers": ["http://127.0.0.1/announce", "http://10.0.0.2/announce"] - })) + response = await self.endpoint.create_torrent(request) response_body_json = await response_to_json(response) _, call_params, __ = mocked_create_torrent_file.call_args.args @@ -152,10 +147,11 @@ async def test_create_with_name(self) -> None: """ Test if creating a torrent with a custom name works. """ + request = MockRequest("/api/createtorrent", "POST", {"files": [str(Path(__file__))], "name": "test"}) mocked_create_torrent_file = Mock(return_value={"metainfo": TORRENT_WITH_DIRS_CONTENT}) + with patch.dict(ep_module.__dict__, {"create_torrent_file": mocked_create_torrent_file}): - response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))], - "name": "test"})) + response = await self.endpoint.create_torrent(request) response_body_json = await response_to_json(response) _, call_params, __ = mocked_create_torrent_file.call_args.args @@ -170,14 +166,15 @@ async def test_create_and_start(self) -> None: """ self.download_manager.config = MockTriblerConfigManager() self.download_manager.start_download = AsyncMock() + request = MockRequest("/api/createtorrent", "POST", {"files": [str(Path(__file__))], "download": "1"}) mocked_create = Mock(return_value={"metainfo": TORRENT_WITH_DIRS_CONTENT, "base_dir": str(Path(__file__).parent)}) + with patch("tribler.core.libtorrent.download_manager.download_config.DownloadConfig.from_defaults", lambda _: DownloadConfig(ConfigObj(StringIO(SPEC_CONTENT)))), patch.dict(ep_module.__dict__, {"create_torrent_file": mocked_create}): - response = await self.endpoint.create_torrent(CreateTorrentRequest({"files": [str(Path(__file__))], - "download": "1"})) + response = await self.endpoint.create_torrent(request) response_body_json = await response_to_json(response) _, tdef, __ = self.download_manager.start_download.call_args.args diff --git a/src/tribler/test_unit/core/libtorrent/restapi/test_downloads_endpoint.py b/src/tribler/test_unit/core/libtorrent/restapi/test_downloads_endpoint.py index e017a9e6c8..30b63098f6 100644 --- a/src/tribler/test_unit/core/libtorrent/restapi/test_downloads_endpoint.py +++ b/src/tribler/test_unit/core/libtorrent/restapi/test_downloads_endpoint.py @@ -3,7 +3,6 @@ """ from __future__ import annotations -from binascii import hexlify from io import StringIO from pathlib import Path from unittest.mock import AsyncMock, Mock, call, patch @@ -11,6 +10,7 @@ from aiohttp.web_urldispatcher import UrlMappingMatchInfo from configobj import ConfigObj from ipv8.test.base import TestBase +from ipv8.test.REST.rest_base import BodyCapture, MockRequest, response_to_bytes, response_to_json from validate import Validator from tribler.core.libtorrent.download_manager.download import Download @@ -19,239 +19,10 @@ from tribler.core.libtorrent.restapi.downloads_endpoint import DownloadsEndpoint from tribler.core.libtorrent.torrentdef import TorrentDef, TorrentDefNoMetainfo from tribler.core.restapi.rest_endpoint import HTTP_BAD_REQUEST, HTTP_INTERNAL_SERVER_ERROR, HTTP_NOT_FOUND -from tribler.test_unit.base_restapi import BodyCapture, MockRequest, response_to_bytes, response_to_json from tribler.test_unit.core.libtorrent.mocks import TORRENT_WITH_DIRS, TORRENT_WITH_DIRS_CONTENT, TORRENT_WITH_VIDEO from tribler.test_unit.mocks import MockTriblerConfigManager -class GetDownloadsRequest(MockRequest): - """ - A MockRequest that mimics GetDownloadsRequests. - """ - - def __init__(self, query: dict) -> None: - """ - Create a new GetDownloadsRequest. - """ - super().__init__(query, "GET", "/downloads") - - -class AddDownloadRequest(MockRequest): - """ - A MockRequest that mimics AddDownloadRequests. - """ - - def __init__(self, query: dict) -> None: - """ - Create a new AddDownloadRequest. - """ - super().__init__(query, "PUT", "/downloads") - - async def json(self) -> dict: - """ - Get the json equivalent of the query (i.e., just the query). - """ - return self._query - - -class DeleteDownloadRequest(MockRequest): - """ - A MockRequest that mimics DeleteDownloadRequests. - """ - - def __init__(self, query: dict, infohash: str) -> None: - """ - Create a new DeleteDownloadRequest. - """ - super().__init__(query, "DELETE", f"/downloads/{infohash}") - self._infohash = infohash - - @property - def match_info(self) -> UrlMappingMatchInfo: - """ - Get the match info (the infohash in the url). - """ - return UrlMappingMatchInfo({"infohash": self._infohash}, Mock()) - - async def json(self) -> dict: - """ - Get the json equivalent of the query (i.e., just the query). - """ - return self._query - - -class UpdateDownloadRequest(MockRequest): - """ - A MockRequest that mimics UpdateDownloadRequests. - """ - - def __init__(self, query: dict, infohash: str) -> None: - """ - Create a new UpdateDownloadRequest. - """ - super().__init__(query, "PATCH", f"/downloads/{infohash}") - self._infohash = infohash - - @property - def match_info(self) -> UrlMappingMatchInfo: - """ - Get the match info (the infohash in the url). - """ - return UrlMappingMatchInfo({"infohash": self._infohash}, Mock()) - - async def json(self) -> dict: - """ - Get the json equivalent of the query (i.e., just the query). - """ - return self._query - - -class GetTorrentRequest(MockRequest): - """ - A MockRequest that mimics GetTorrentRequests. - """ - - def __init__(self, query: dict, infohash: str) -> None: - """ - Create a new GetTorrentRequest. - """ - super().__init__(query, "GET", f"/downloads/{infohash}/torrent") - self._infohash = infohash - - @property - def match_info(self) -> UrlMappingMatchInfo: - """ - Get the match info (the infohash in the url). - """ - return UrlMappingMatchInfo({"infohash": self._infohash}, Mock()) - - -class GetFilesRequest(MockRequest): - """ - A MockRequest that mimics GetFilesRequests. - """ - - def __init__(self, query: dict, infohash: str) -> None: - """ - Create a new GetFilesRequest. - """ - super().__init__(query, "GET", f"/downloads/{infohash}/files") - self._infohash = infohash - - @property - def match_info(self) -> UrlMappingMatchInfo: - """ - Get the match info (the infohash in the url). - """ - return UrlMappingMatchInfo({"infohash": self._infohash}, Mock()) - - -class ExpandTreeDirectoryRequest(MockRequest): - """ - A MockRequest that mimics ExpandTreeDirectoryRequests. - """ - - def __init__(self, query: dict, infohash: str) -> None: - """ - Create a new ExpandTreeDirectoryRequest. - """ - super().__init__(query, "GET", f"/downloads/{infohash}/files/expand") - self._infohash = infohash - - @property - def match_info(self) -> UrlMappingMatchInfo: - """ - Get the match info (the infohash in the url). - """ - return UrlMappingMatchInfo({"infohash": self._infohash}, Mock()) - - -class CollapseTreeDirectoryRequest(MockRequest): - """ - A MockRequest that mimics CollapseTreeDirectoryRequests. - """ - - def __init__(self, query: dict, infohash: str) -> None: - """ - Create a new CollapseTreeDirectoryRequest. - """ - super().__init__(query, "GET", f"/downloads/{infohash}/files/collapse") - self._infohash = infohash - - @property - def match_info(self) -> UrlMappingMatchInfo: - """ - Get the match info (the infohash in the url). - """ - return UrlMappingMatchInfo({"infohash": self._infohash}, Mock()) - - -class SelectTreePathRequest(MockRequest): - """ - A MockRequest that mimics SelectTreePathRequests. - """ - - def __init__(self, query: dict, infohash: str) -> None: - """ - Create a new SelectTreePathRequest. - """ - super().__init__(query, "GET", f"/downloads/{infohash}/files/select") - self._infohash = infohash - - @property - def match_info(self) -> UrlMappingMatchInfo: - """ - Get the match info (the infohash in the url). - """ - return UrlMappingMatchInfo({"infohash": self._infohash}, Mock()) - - -class DeselectTreePathRequest(MockRequest): - """ - A MockRequest that mimics DeselectTreePathRequests. - """ - - def __init__(self, query: dict, infohash: str) -> None: - """ - Create a new DeselectTreePathRequest. - """ - super().__init__(query, "GET", f"/downloads/{infohash}/files/deselect") - self._infohash = infohash - - @property - def match_info(self) -> UrlMappingMatchInfo: - """ - Get the match info (the infohash in the url). - """ - return UrlMappingMatchInfo({"infohash": self._infohash}, Mock()) - - -class GenericTrackerRequest(MockRequest): - """ - A MockRequest that mimics requests to add, remove or check trackers. - """ - - def __init__(self, infohash: str, url: str | None, method: str, sub_endpoint: str) -> None: - """ - Create a new AddDownloadRequest. - """ - super().__init__({"url": url}, method, f"/downloads/{infohash}/{sub_endpoint}") - self._infohash = infohash - - async def json(self) -> dict: - """ - Get the json equivalent of the query (i.e., just the query). - """ - return self._query - - @property - def match_info(self) -> UrlMappingMatchInfo: - """ - Get the match info (the infohash in the url). - """ - return UrlMappingMatchInfo({"infohash": self._infohash}, Mock()) - - class StreamRequest(MockRequest): """ A MockRequest that mimics StreamRequests. @@ -263,7 +34,7 @@ def __init__(self, query: dict, infohash: str, fileindex: int, **kwargs) -> None """ Create a new StreamRequest. """ - super().__init__(query, "GET", f"/downloads/{infohash}/stream/{fileindex}") + super().__init__(f"/downloads/{infohash}/stream/{fileindex}", "GET", query) self._infohash = infohash self._fileindex = fileindex self._payload_writer = BodyCapture() @@ -327,8 +98,9 @@ async def test_get_downloads_unloaded(self) -> None: self.download_manager.checkpoints_loaded = 0 self.download_manager.all_checkpoints_are_loaded = False self.download_manager.get_downloads = Mock(return_value=[]) + request = MockRequest("/api/downloads", query={}) - response = await self.endpoint.get_downloads(GetDownloadsRequest({})) + response = await self.endpoint.get_downloads(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -342,8 +114,9 @@ async def test_get_downloads_no_downloads(self) -> None: Test if an empty list is returned if there are no downloads. """ self.set_loaded_downloads([]) + request = MockRequest("/api/downloads", query={}) - response = await self.endpoint.get_downloads(GetDownloadsRequest({})) + response = await self.endpoint.get_downloads(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -358,8 +131,9 @@ async def test_get_downloads_hidden_download(self) -> None: """ self.set_loaded_downloads([Download(TorrentDefNoMetainfo(b"\x01" * 20, b"test"), None, Mock(), hidden=True, checkpoint_disabled=True)]) + request = MockRequest("/api/downloads", query={}) - response = await self.endpoint.get_downloads(GetDownloadsRequest({})) + response = await self.endpoint.get_downloads(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -373,8 +147,9 @@ async def test_get_downloads_normal_download(self) -> None: Test if the information of a normal download is correctly presented. """ self.set_loaded_downloads([self.create_mock_download()]) + request = MockRequest("/api/downloads", query={}) - response = await self.endpoint.get_downloads(GetDownloadsRequest({})) + response = await self.endpoint.get_downloads(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -415,9 +190,10 @@ async def test_get_downloads_filter_download_pass(self) -> None: download = self.create_mock_download() download.handle = Mock(is_valid=Mock(return_value=False), status=Mock(return_value=Mock(pieces=[False]))) self.set_loaded_downloads([download]) + request = MockRequest("/api/downloads", query={"infohash": "01" * 20, "get_peers": "1", + "get_pieces": "1", "get_availability": "1"}) - response = await self.endpoint.get_downloads(GetDownloadsRequest({"infohash": "01" * 20, "get_peers": "1", - "get_pieces": "1", "get_availability": "1"})) + response = await self.endpoint.get_downloads(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -433,9 +209,10 @@ async def test_get_downloads_filter_download_fail(self) -> None: download = self.create_mock_download() download.handle = Mock(is_valid=Mock(return_value=False), status=Mock(return_value=Mock(pieces=[False]))) self.set_loaded_downloads([download]) + request = MockRequest("/api/downloads", query={"infohash": "02" * 20, "get_peers": "1", + "get_pieces": "1", "get_availability": "1"}) - response = await self.endpoint.get_downloads(GetDownloadsRequest({"infohash": "02" * 20, "get_peers": "1", - "get_pieces": "1", "get_availability": "1"})) + response = await self.endpoint.get_downloads(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -453,8 +230,9 @@ async def test_get_downloads_stream_download(self) -> None: download.stream = Stream(download) download.stream.close() self.set_loaded_downloads([download]) + request = MockRequest("/api/downloads", query={}) - response = await self.endpoint.get_downloads(GetDownloadsRequest({})) + response = await self.endpoint.get_downloads(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -468,7 +246,9 @@ async def test_add_download_no_uri(self) -> None: """ Test if a graceful error is returned when no uri is given. """ - response = await self.endpoint.add_download(AddDownloadRequest({})) + request = MockRequest("/api/downloads", "PUT", {}) + + response = await self.endpoint.add_download(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -479,10 +259,12 @@ async def test_add_download_unsafe_anon_error(self) -> None: Test if a graceful error is returned when safe seeding is not enabled in anonymous mode. """ download = self.create_mock_download() + request = MockRequest("/api/downloads", "PUT", {"uri": "http://127.0.0.1/file", + "anon_hops": 1, "safe_seeding": 0}) + with patch("tribler.core.libtorrent.download_manager.download_config.DownloadConfig.from_defaults", lambda _: download.config): - response = await self.endpoint.add_download(AddDownloadRequest({"uri": "http://127.0.0.1/file", - "anon_hops": 1, "safe_seeding": 0})) + response = await self.endpoint.add_download(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -495,9 +277,11 @@ async def test_add_download_default_parameters(self) -> None: """ download = self.create_mock_download() self.download_manager.start_download_from_uri = AsyncMock(return_value=download) + request = MockRequest("/api/downloads", "PUT", {"uri": "http://127.0.0.1/file"}) + with patch("tribler.core.libtorrent.download_manager.download_config.DownloadConfig.from_defaults", lambda _: download.config): - response = await self.endpoint.add_download(AddDownloadRequest({"uri": "http://127.0.0.1/file"})) + response = await self.endpoint.add_download(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -514,11 +298,12 @@ async def test_add_download_custom_parameters(self) -> None: """ download = self.create_mock_download() self.download_manager.start_download_from_uri = AsyncMock(return_value=download) + request = MockRequest("/api/downloads", "PUT", {"uri": "http://127.0.0.1/file", "safe_seeding": 1, + "selected_files": [0], "destination": "foo", "anon_hops": 1}) + with patch("tribler.core.libtorrent.download_manager.download_config.DownloadConfig.from_defaults", lambda _: download.config): - response = await self.endpoint.add_download(AddDownloadRequest({"uri": "http://127.0.0.1/file", - "safe_seeding": 1, "selected_files": [0], - "destination": "foo", "anon_hops": 1})) + response = await self.endpoint.add_download(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -535,9 +320,11 @@ async def test_add_download_failed(self) -> None: """ download = self.create_mock_download() self.download_manager.start_download_from_uri = AsyncMock(side_effect=Exception("invalid uri")) + request = MockRequest("/api/downloads", "PUT", {"uri": "http://127.0.0.1/file"}) + with patch("tribler.core.libtorrent.download_manager.download_config.DownloadConfig.from_defaults", lambda _: download.config): - response = await self.endpoint.add_download(AddDownloadRequest({"uri": "http://127.0.0.1/file"})) + response = await self.endpoint.add_download(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -547,7 +334,9 @@ async def test_delete_download_no_remove_data(self) -> None: """ Test if a graceful error is returned when no remove data is supplied when deleting a download. """ - response = await self.endpoint.delete_download(DeleteDownloadRequest({}, "01" * 20)) + request = MockRequest("/api/downloads/" + "01" * 20, "DELETE", {}, {"infohash": "01" * 20}) + + response = await self.endpoint.delete_download(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -558,8 +347,9 @@ async def test_delete_download_no_download(self) -> None: Test if a graceful error is returned when no download is found for removal. """ self.download_manager.get_download = Mock(return_value=None) + request = MockRequest("/api/downloads/" + "01" * 20, "DELETE", {"remove_data": False}, {"infohash": "01" * 20}) - response = await self.endpoint.delete_download(DeleteDownloadRequest({"remove_data": False}, "01" * 20)) + response = await self.endpoint.delete_download(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_NOT_FOUND, response.status) @@ -572,8 +362,9 @@ async def test_delete_download_no_data(self) -> None: download = self.create_mock_download() self.download_manager.get_download = Mock(return_value=download) self.download_manager.remove_download = AsyncMock() + request = MockRequest("/api/downloads/" + "01" * 20, "DELETE", {"remove_data": False}, {"infohash": "01" * 20}) - response = await self.endpoint.delete_download(DeleteDownloadRequest({"remove_data": False}, "01" * 20)) + response = await self.endpoint.delete_download(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -588,8 +379,9 @@ async def test_delete_download_with_data(self) -> None: download = self.create_mock_download() self.download_manager.get_download = Mock(return_value=download) self.download_manager.remove_download = AsyncMock() + request = MockRequest("/api/downloads/" + "01" * 20, "DELETE", {"remove_data": True}, {"infohash": "01" * 20}) - response = await self.endpoint.delete_download(DeleteDownloadRequest({"remove_data": True}, "01" * 20)) + response = await self.endpoint.delete_download(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -604,8 +396,9 @@ async def test_delete_download_delete_failed(self) -> None: download = self.create_mock_download() self.download_manager.get_download = Mock(return_value=download) self.download_manager.remove_download = AsyncMock(side_effect=OSError) + request = MockRequest("/api/downloads/" + "01" * 20, "DELETE", {"remove_data": False}, {"infohash": "01" * 20}) - response = await self.endpoint.delete_download(DeleteDownloadRequest({"remove_data": False}, "01" * 20)) + response = await self.endpoint.delete_download(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -617,8 +410,9 @@ async def test_update_download_no_download(self) -> None: Test if a graceful error is returned when no download is found to update. """ self.download_manager.get_download = Mock(return_value=None) + request = MockRequest("/api/downloads/" + "01" * 20, "PATCH", {}, {"infohash": "01" * 20}) - response = await self.endpoint.update_download(UpdateDownloadRequest({}, "01" * 20)) + response = await self.endpoint.update_download(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_NOT_FOUND, response.status) @@ -628,8 +422,10 @@ async def test_update_download_anon_hops_garbage(self) -> None: """ Test if anon hops can only exist as the only parameter. """ - response = await self.endpoint.update_download(UpdateDownloadRequest({"anon_hops": 1, "foo": "bar"}, - "01" * 20)) + request = MockRequest("/api/downloads/" + "01" * 20, "PATCH", {"anon_hops": 1, "foo": "bar"}, + {"infohash": "01" * 20}) + + response = await self.endpoint.update_download(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -642,8 +438,9 @@ async def test_update_download_anon_hops_update(self) -> None: download = self.create_mock_download() self.download_manager.get_download = Mock(return_value=download) self.download_manager.update_hops = AsyncMock() + request = MockRequest("/api/downloads/" + "01" * 20, "PATCH", {"anon_hops": 1}, {"infohash": "01" * 20}) - response = await self.endpoint.update_download(UpdateDownloadRequest({"anon_hops": 1}, "01" * 20)) + response = await self.endpoint.update_download(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -657,8 +454,9 @@ async def test_update_download_anon_hops_update_failed(self) -> None: download = self.create_mock_download() self.download_manager.get_download = Mock(return_value=download) self.download_manager.update_hops = AsyncMock(side_effect=OSError) + request = MockRequest("/api/downloads/" + "01" * 20, "PATCH", {"anon_hops": 1}, {"infohash": "01" * 20}) - response = await self.endpoint.update_download(UpdateDownloadRequest({"anon_hops": 1}, "01" * 20)) + response = await self.endpoint.update_download(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -672,9 +470,10 @@ async def test_update_download_selected_files_out_of_range(self) -> None: download = self.create_mock_download() download.tdef.metainfo = {b"info": {b"files": [{b"path": {b"hi.txt"}, b"length": 0}]}} self.download_manager.get_download = Mock(return_value=download) + request = MockRequest("/api/downloads/" + "01" * 20, "PATCH", {"selected_files": [99999999999]}, + {"infohash": "01" * 20}) - response = await self.endpoint.update_download(UpdateDownloadRequest({"selected_files": [99999999999]}, - "01" * 20)) + response = await self.endpoint.update_download(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -687,9 +486,9 @@ async def test_update_download_selected_files(self) -> None: download = self.create_mock_download() download.tdef.metainfo = {b"info": {b"files": [{b"path": {b"hi.txt"}, b"length": 0}]}} self.download_manager.get_download = Mock(return_value=download) + request = MockRequest("/api/downloads/" + "01" * 20, "PATCH", {"selected_files": [0]}, {"infohash": "01" * 20}) - response = await self.endpoint.update_download(UpdateDownloadRequest({"selected_files": [0]}, - "01" * 20)) + response = await self.endpoint.update_download(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -702,8 +501,9 @@ async def test_update_download_unknown_state(self) -> None: """ download = self.create_mock_download() self.download_manager.get_download = Mock(return_value=download) + request = MockRequest("/api/downloads/" + "01" * 20, "PATCH", {"state": "foo"}, {"infohash": "01" * 20}) - response = await self.endpoint.update_download(UpdateDownloadRequest({"state": "foo"}, "01" * 20)) + response = await self.endpoint.update_download(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -716,8 +516,9 @@ async def test_update_download_state_resume(self) -> None: download = self.create_mock_download() download.config.set_user_stopped(True) self.download_manager.get_download = Mock(return_value=download) + request = MockRequest("/api/downloads/" + "01" * 20, "PATCH", {"state": "resume"}, {"infohash": "01" * 20}) - response = await self.endpoint.update_download(UpdateDownloadRequest({"state": "resume"}, "01" * 20)) + response = await self.endpoint.update_download(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -732,8 +533,9 @@ async def test_update_download_state_stop(self) -> None: download = self.create_mock_download() download.config.set_user_stopped(False) self.download_manager.get_download = Mock(return_value=download) + request = MockRequest("/api/downloads/" + "01" * 20, "PATCH", {"state": "stop"}, {"infohash": "01" * 20}) - response = await self.endpoint.update_download(UpdateDownloadRequest({"state": "stop"}, "01" * 20)) + response = await self.endpoint.update_download(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -749,8 +551,9 @@ async def test_update_download_state_recheck(self) -> None: download.tdef = Mock(get_infohash=Mock(return_value=b"\x01" * 20)) download.handle = Mock(is_valid=Mock(return_value=True)) self.download_manager.get_download = Mock(return_value=download) + request = MockRequest("/api/downloads/" + "01" * 20, "PATCH", {"state": "recheck"}, {"infohash": "01" * 20}) - response = await self.endpoint.update_download(UpdateDownloadRequest({"state": "recheck"}, "01" * 20)) + response = await self.endpoint.update_download(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -764,10 +567,10 @@ async def test_update_download_state_move_storage_no_dest_dir(self) -> None: """ download = self.create_mock_download() self.download_manager.get_download = Mock(return_value=download) + request = MockRequest("/api/downloads/" + "01" * 20, "PATCH", + {"state": "move_storage", "dest_dir": "I don't exist"}, {"infohash": "01" * 20}) - response = await self.endpoint.update_download(UpdateDownloadRequest({"state": "move_storage", - "dest_dir": "I don't exist"}, - "01" * 20)) + response = await self.endpoint.update_download(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -781,10 +584,11 @@ async def test_update_download_state_move_storage(self) -> None: download.tdef = Mock(get_infohash=Mock(return_value=b"\x01" * 20)) download.handle = Mock(is_valid=Mock(return_value=True)) self.download_manager.get_download = Mock(return_value=download) + request = MockRequest("/api/downloads/" + "01" * 20, "PATCH", + {"state": "move_storage", "dest_dir": str(Path(__file__).parent)}, + {"infohash": "01" * 20}) - response = await self.endpoint.update_download(UpdateDownloadRequest({"state": "move_storage", - "dest_dir": str(Path(__file__).parent)}, - "01" * 20)) + response = await self.endpoint.update_download(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -798,8 +602,9 @@ async def test_update_download_nothing(self) -> None: """ download = self.create_mock_download() self.download_manager.get_download = Mock(return_value=download) + request = MockRequest("/api/downloads/" + "01" * 20, "PATCH", {}, {"infohash": "01" * 20}) - response = await self.endpoint.update_download(UpdateDownloadRequest({}, "01" * 20)) + response = await self.endpoint.update_download(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -811,8 +616,9 @@ async def test_get_torrent_no_download(self) -> None: Test if a graceful error is returned when no download is found. """ self.download_manager.get_download = Mock(return_value=None) + request = MockRequest(f"/api/downloads/{'01' * 20}/torrent", "GET", {}, {"infohash": "01" * 20}) - response = await self.endpoint.get_torrent(GetTorrentRequest({}, "01" * 20)) + response = await self.endpoint.get_torrent(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_NOT_FOUND, response.status) @@ -823,8 +629,9 @@ async def test_get_torrent_no_torrent_data(self) -> None: Test if a graceful error is returned when no torrent data is found. """ self.download_manager.get_download = Mock(return_value=Mock(get_torrent_data=Mock(return_value=None))) + request = MockRequest(f"/api/downloads/{'01' * 20}/torrent", "GET", {}, {"infohash": "01" * 20}) - response = await self.endpoint.get_torrent(GetTorrentRequest({}, "01" * 20)) + response = await self.endpoint.get_torrent(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_NOT_FOUND, response.status) @@ -837,8 +644,9 @@ async def test_get_torrent(self) -> None: download = self.create_mock_download() download.handle = Mock(is_valid=Mock(return_value=True), torrent_file=Mock(return_value=TORRENT_WITH_DIRS)) self.download_manager.get_download = Mock(return_value=download) + request = MockRequest(f"/api/downloads/{'01' * 20}/torrent", "GET", {}, {"infohash": "01" * 20}) - response = await self.endpoint.get_torrent(GetTorrentRequest({}, "01" * 20)) + response = await self.endpoint.get_torrent(request) response_body_bytes = await response_to_bytes(response) self.assertEqual(200, response.status) @@ -849,8 +657,9 @@ async def test_get_files_no_download(self) -> None: Test if a graceful error is returned when no download is found. """ self.download_manager.get_download = Mock(return_value=None) + request = MockRequest(f"/api/downloads/{'01' * 20}/files", "GET", {}, {"infohash": "01" * 20}) - response = await self.endpoint.get_files(GetFilesRequest({}, "01" * 20)) + response = await self.endpoint.get_files(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_NOT_FOUND, response.status) @@ -863,8 +672,9 @@ async def test_get_files_without_path(self) -> None: download = self.create_mock_download() download.tdef = TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT) self.download_manager.get_download = Mock(return_value=download) + request = MockRequest(f"/api/downloads/{'01' * 20}/files", "GET", {}, {"infohash": "01" * 20}) - response = await self.endpoint.get_files(GetFilesRequest({}, "01" * 20)) + response = await self.endpoint.get_files(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -878,9 +688,10 @@ async def test_get_files_with_path_unloaded(self) -> None: download = self.create_mock_download() download.tdef = TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT) self.download_manager.get_download = Mock(return_value=download) + request = MockRequest(f"/api/downloads/{'01' * 20}/files", "GET", + {"view_start_path": "def/file6.avi", "view_size": 2}, {"infohash": "01" * 20}) - response = await self.endpoint.get_files(GetFilesRequest({"view_start_path": "def/file6.avi", "view_size": 2}, - "01" * 20)) + response = await self.endpoint.get_files(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -901,9 +712,10 @@ async def test_get_files_with_path(self) -> None: download.tdef.load_torrent_info() download.tdef.torrent_file_tree.expand(Path("torrent_create/abc")) self.download_manager.get_download = Mock(return_value=download) + request = MockRequest(f"/api/downloads/{'01' * 20}/files", "GET", + {"view_start_path": "torrent_create", "view_size": 2}, {"infohash": "01" * 20}) - response = await self.endpoint.get_files(GetFilesRequest({"view_start_path": "torrent_create", "view_size": 2}, - "01" * 20)) + response = await self.endpoint.get_files(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -925,8 +737,9 @@ async def test_collapse_tree_directory_no_download(self) -> None: Test if a graceful error is returned when no download is found. """ self.download_manager.get_download = Mock(return_value=None) + request = MockRequest(f"/api/downloads/{'01' * 20}/files/collapse", "GET", {}, {"infohash": "01" * 20}) - response = await self.endpoint.collapse_tree_directory(CollapseTreeDirectoryRequest({}, "01" * 20)) + response = await self.endpoint.collapse_tree_directory(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_NOT_FOUND, response.status) @@ -941,10 +754,10 @@ async def test_collapse_tree_directory(self) -> None: download.tdef.load_torrent_info() download.tdef.torrent_file_tree.expand(Path("torrent_create/abc")) self.download_manager.get_download = Mock(return_value=download) + request = MockRequest(f"/api/downloads/{'01' * 20}/files/collapse", "GET", + {"path": "torrent_create/abc"}, {"infohash": "01" * 20}) - response = await self.endpoint.collapse_tree_directory(CollapseTreeDirectoryRequest( - {"path": "torrent_create/abc"}, "01" * 20 - )) + response = await self.endpoint.collapse_tree_directory(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -956,8 +769,9 @@ async def test_expand_tree_directory_no_download(self) -> None: Test if a graceful error is returned when no download is found. """ self.download_manager.get_download = Mock(return_value=None) + request = MockRequest(f"/api/downloads/{'01' * 20}/files/expand", "GET", {}, {"infohash": "01" * 20}) - response = await self.endpoint.expand_tree_directory(ExpandTreeDirectoryRequest({}, "01" * 20)) + response = await self.endpoint.expand_tree_directory(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_NOT_FOUND, response.status) @@ -971,10 +785,10 @@ async def test_expand_tree_directory(self) -> None: download.tdef = TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT) download.tdef.load_torrent_info() self.download_manager.get_download = Mock(return_value=download) + request = MockRequest(f"/api/downloads/{'01' * 20}/files/expand", "GET", + {"path": "torrent_create/abc"}, {"infohash": "01" * 20}) - response = await self.endpoint.expand_tree_directory(ExpandTreeDirectoryRequest( - {"path": "torrent_create/abc"}, "01" * 20 - )) + response = await self.endpoint.expand_tree_directory(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -986,8 +800,9 @@ async def test_select_tree_path_no_download(self) -> None: Test if a graceful error is returned when no download is found. """ self.download_manager.get_download = Mock(return_value=None) + request = MockRequest(f"/api/downloads/{'01' * 20}/files/select", "GET", {}, {"infohash": "01" * 20}) - response = await self.endpoint.select_tree_path(SelectTreePathRequest({}, "01" * 20)) + response = await self.endpoint.select_tree_path(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_NOT_FOUND, response.status) @@ -1002,10 +817,10 @@ async def test_select_tree_path(self) -> None: download.tdef = TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT) download.tdef.load_torrent_info() self.download_manager.get_download = Mock(return_value=download) + request = MockRequest(f"/api/downloads/{'01' * 20}/files/select", "GET", + {"path": "torrent_create/def/file6.avi"}, {"infohash": "01" * 20}) - response = await self.endpoint.select_tree_path(SelectTreePathRequest( - {"path": "torrent_create/def/file6.avi"}, "01" * 20 - )) + response = await self.endpoint.select_tree_path(request) self.assertEqual(200, response.status) self.assertTrue(download.tdef.torrent_file_tree.find(Path("torrent_create/def/file6.avi")).selected) @@ -1015,8 +830,9 @@ async def test_deselect_tree_path_no_download(self) -> None: Test if a graceful error is returned when no download is found. """ self.download_manager.get_download = Mock(return_value=None) + request = MockRequest(f"/api/downloads/{'01' * 20}/files/deselect", "GET", {}, {"infohash": "01" * 20}) - response = await self.endpoint.deselect_tree_path(DeselectTreePathRequest({}, "01" * 20)) + response = await self.endpoint.deselect_tree_path(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_NOT_FOUND, response.status) @@ -1031,10 +847,10 @@ async def test_deselect_tree_path(self) -> None: download.tdef = TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT) download.tdef.load_torrent_info() self.download_manager.get_download = Mock(return_value=download) + request = MockRequest(f"/api/downloads/{'01' * 20}/files/deselect", "GET", + {"path": "torrent_create/def/file6.avi"}, {"infohash": "01" * 20}) - response = await self.endpoint.deselect_tree_path(DeselectTreePathRequest( - {"path": "torrent_create/def/file6.avi"}, "01" * 20 - )) + response = await self.endpoint.deselect_tree_path(request) self.assertEqual(200, response.status) self.assertFalse(download.tdef.torrent_file_tree.find(Path("torrent_create/def/file6.avi")).selected) @@ -1113,10 +929,9 @@ async def test_add_tracker(self) -> None: add_tracker=lambda tracker_dict: trackers.append(tracker_dict["url"])) self.download_manager.get_download = Mock(return_value=download) url = "http://127.0.0.1/announce" + request = MockRequest(f"/api/downloads/{'01' * 20}/trackers", "PUT", {"url": url}, {"infohash": "01" * 20}) - response = await self.endpoint.add_tracker( - GenericTrackerRequest(hexlify(download.tdef.infohash).decode(), url, "PUT", "trackers") - ) + response = await self.endpoint.add_tracker(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -1129,9 +944,10 @@ async def test_add_tracker_no_download(self) -> None: Test if adding a tracker fails when no download is found. """ self.download_manager.get_download = Mock(return_value=None) + request = MockRequest(f"/api/downloads/{'AA' * 20}/trackers", "PUT", {"url": "http://127.0.0.1/announce"}, + {"infohash": "AA" * 20}) - response = await self.endpoint.add_tracker(GenericTrackerRequest("AA" * 20, "http://127.0.0.1/announce", - "PUT", "trackers")) + response = await self.endpoint.add_tracker(request) self.assertEqual(404, response.status) @@ -1142,8 +958,9 @@ async def test_add_tracker_no_url(self) -> None: download = self.create_mock_download() download.handle = Mock(is_valid=Mock(return_value=True), trackers=Mock(return_value=[])) self.download_manager.get_download = Mock(return_value=download) + request = MockRequest(f"/api/downloads/{'AA' * 20}/trackers", "PUT", {"url": None}, {"infohash": "AA" * 20}) - response = await self.endpoint.add_tracker(GenericTrackerRequest("AA" * 20, None, "PUT", "trackers")) + response = await self.endpoint.add_tracker(request) self.assertEqual(400, response.status) @@ -1157,10 +974,9 @@ async def test_add_tracker_handle_error(self) -> None: add_tracker=Mock(side_effect=RuntimeError("invalid torrent handle used"))) self.download_manager.get_download = Mock(return_value=download) url = "http://127.0.0.1/announce" + request = MockRequest(f"/api/downloads/{'01' * 20}/trackers", "PUT", {"url": url}, {"infohash": "01" * 20}) - response = await self.endpoint.add_tracker( - GenericTrackerRequest(hexlify(download.tdef.infohash).decode(), url, "PUT", "trackers") - ) + response = await self.endpoint.add_tracker(request) response_body_json = await response_to_json(response) self.assertEqual(500, response.status) @@ -1178,10 +994,9 @@ async def test_remove_tracker(self) -> None: is trackers.extend(new_trackers))) self.download_manager.get_download = Mock(return_value=download) url = "http://127.0.0.1/announce" + request = MockRequest(f"/api/downloads/{'01' * 20}/trackers", "DELETE", {"url": url}, {"infohash": "01" * 20}) - response = await self.endpoint.remove_tracker( - GenericTrackerRequest(hexlify(download.tdef.infohash).decode(), url, "DELETE", "trackers") - ) + response = await self.endpoint.remove_tracker(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -1198,10 +1013,9 @@ async def test_remove_tracker_from_metainfo_announce(self) -> None: download.handle = Mock(is_valid=Mock(return_value=True), trackers=Mock(return_value=[])) self.download_manager.get_download = Mock(return_value=download) url = "http://127.0.0.1/announce" + request = MockRequest(f"/api/downloads/{'01' * 20}/trackers", "DELETE", {"url": url}, {"infohash": "01" * 20}) - response = await self.endpoint.remove_tracker( - GenericTrackerRequest(hexlify(download.tdef.infohash).decode(), url, "DELETE", "trackers") - ) + response = await self.endpoint.remove_tracker(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -1218,10 +1032,9 @@ async def test_remove_tracker_from_metainfo_announce_list(self) -> None: download.handle = Mock(is_valid=Mock(return_value=True), trackers=Mock(return_value=[])) self.download_manager.get_download = Mock(return_value=download) url = "http://127.0.0.1/announce" + request = MockRequest(f"/api/downloads/{'01' * 20}/trackers", "DELETE", {"url": url}, {"infohash": "01" * 20}) - response = await self.endpoint.remove_tracker( - GenericTrackerRequest(hexlify(download.tdef.infohash).decode(), url, "DELETE", "trackers") - ) + response = await self.endpoint.remove_tracker(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -1240,10 +1053,9 @@ async def test_remove_tracker_from_metainfo_announce_both_first(self) -> None: download.handle = Mock(is_valid=Mock(return_value=True), trackers=Mock(return_value=[])) self.download_manager.get_download = Mock(return_value=download) url = "http://127.0.0.1/announce" + request = MockRequest(f"/api/downloads/{'01' * 20}/trackers", "DELETE", {"url": url}, {"infohash": "01" * 20}) - response = await self.endpoint.remove_tracker( - GenericTrackerRequest(hexlify(download.tdef.infohash).decode(), url, "DELETE", "trackers") - ) + response = await self.endpoint.remove_tracker(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -1263,10 +1075,9 @@ async def test_remove_tracker_from_metainfo_announce_both_second(self) -> None: download.handle = Mock(is_valid=Mock(return_value=True), trackers=Mock(return_value=[])) self.download_manager.get_download = Mock(return_value=download) url = "http://127.0.0.1/announce" + request = MockRequest(f"/api/downloads/{'01' * 20}/trackers", "DELETE", {"url": url}, {"infohash": "01" * 20}) - response = await self.endpoint.remove_tracker( - GenericTrackerRequest(hexlify(download.tdef.infohash).decode(), url, "DELETE", "trackers") - ) + response = await self.endpoint.remove_tracker(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -1280,9 +1091,10 @@ async def test_remove_tracker_no_download(self) -> None: Test if removing a tracker fails when no download is found. """ self.download_manager.get_download = Mock(return_value=None) + request = MockRequest(f"/api/downloads/{'AA' * 20}/trackers", "DELETE", {"url": "http://127.0.0.1/announce"}, + {"infohash": "AA" * 20}) - response = await self.endpoint.remove_tracker(GenericTrackerRequest("AA" * 20, "http://127.0.0.1/announce", - "DELETE", "trackers")) + response = await self.endpoint.remove_tracker(request) self.assertEqual(404, response.status) @@ -1293,8 +1105,9 @@ async def test_remove_tracker_no_url(self) -> None: download = self.create_mock_download() download.handle = Mock(is_valid=Mock(return_value=True), trackers=Mock(return_value=[])) self.download_manager.get_download = Mock(return_value=download) + request = MockRequest(f"/api/downloads/{'AA' * 20}/trackers", "DELETE", {"url": None}, {"infohash": "AA" * 20}) - response = await self.endpoint.remove_tracker(GenericTrackerRequest("AA" * 20, None, "DELETE", "trackers")) + response = await self.endpoint.remove_tracker(request) self.assertEqual(400, response.status) @@ -1309,10 +1122,9 @@ async def test_remove_tracker_handle_error(self) -> None: replace_trackers=Mock(side_effect=RuntimeError("invalid torrent handle used"))) self.download_manager.get_download = Mock(return_value=download) url = "http://127.0.0.1/announce" + request = MockRequest(f"/api/downloads/{'01' * 20}/trackers", "DELETE", {"url": url}, {"infohash": "01" * 20}) - response = await self.endpoint.remove_tracker( - GenericTrackerRequest(hexlify(download.tdef.infohash).decode(), url, "DELETE", "trackers") - ) + response = await self.endpoint.remove_tracker(request) response_body_json = await response_to_json(response) self.assertEqual(500, response.status) @@ -1328,10 +1140,10 @@ async def test_tracker_force_announce(self) -> None: download.handle = Mock(is_valid=Mock(return_value=True), trackers=Mock(return_value=trackers)) self.download_manager.get_download = Mock(return_value=download) url = "http://127.0.0.1/announce" + request = MockRequest(f"/api/downloads/{'01' * 20}/tracker_force_announce", "PUT", {"url": url}, + {"infohash": "01" * 20}) - response = await self.endpoint.tracker_force_announce( - GenericTrackerRequest(hexlify(download.tdef.infohash).decode(), url, "PUT", "tracker_force_announce") - ) + response = await self.endpoint.tracker_force_announce(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -1343,10 +1155,10 @@ async def test_tracker_force_announce_no_download(self) -> None: Test if force-announcing a tracker fails when no download is found. """ self.download_manager.get_download = Mock(return_value=None) + request = MockRequest(f"/api/downloads/{'AA' * 20}/tracker_force_announce", "PUT", + {"url": "http://127.0.0.1/announce"}, {"infohash": "AA" * 20}) - response = await self.endpoint.tracker_force_announce( - GenericTrackerRequest("AA" * 20, "http://127.0.0.1/announce", "PUT", "tracker_force_announce") - ) + response = await self.endpoint.tracker_force_announce(request) self.assertEqual(404, response.status) @@ -1357,9 +1169,10 @@ async def test_tracker_force_announce_no_url(self) -> None: download = self.create_mock_download() download.handle = Mock(is_valid=Mock(return_value=True), trackers=Mock(return_value=[])) self.download_manager.get_download = Mock(return_value=download) + request = MockRequest(f"/api/downloads/{'AA' * 20}/tracker_force_announce", "PUT", {"url": None}, + {"infohash": "AA" * 20}) - response = await self.endpoint.tracker_force_announce(GenericTrackerRequest("AA" * 20, None, "PUT", - "tracker_force_announce")) + response = await self.endpoint.tracker_force_announce(request) self.assertEqual(400, response.status) @@ -1374,10 +1187,10 @@ async def test_tracker_force_announce_handle_error(self) -> None: force_reannounce=Mock(side_effect=RuntimeError("invalid torrent handle used"))) self.download_manager.get_download = Mock(return_value=download) url = "http://127.0.0.1/announce" + request = MockRequest(f"/api/downloads/{'01' * 20}/tracker_force_announce", "PUT", {"url": url}, + {"infohash": "01" * 20}) - response = await self.endpoint.tracker_force_announce( - GenericTrackerRequest(hexlify(download.tdef.infohash).decode(), url, "PUT", "tracker_force_announce") - ) + response = await self.endpoint.tracker_force_announce(request) response_body_json = await response_to_json(response) self.assertEqual(500, response.status) diff --git a/src/tribler/test_unit/core/libtorrent/restapi/test_libtorrent_endpoint.py b/src/tribler/test_unit/core/libtorrent/restapi/test_libtorrent_endpoint.py index 4ebf4f5b57..5652f2c03c 100644 --- a/src/tribler/test_unit/core/libtorrent/restapi/test_libtorrent_endpoint.py +++ b/src/tribler/test_unit/core/libtorrent/restapi/test_libtorrent_endpoint.py @@ -3,33 +3,9 @@ from unittest.mock import Mock from ipv8.test.base import TestBase +from ipv8.test.REST.rest_base import MockRequest, response_to_json from tribler.core.libtorrent.restapi.libtorrent_endpoint import LibTorrentEndpoint -from tribler.test_unit.base_restapi import MockRequest, response_to_json - - -class GetLibtorrentSettingsRequest(MockRequest): - """ - A MockRequest that mimics GetLibtorrentSettingsRequests. - """ - - def __init__(self, query: dict) -> None: - """ - Create a new GetLibtorrentSettingsRequest. - """ - super().__init__(query, "GET", "/libtorrent/settings") - - -class GetLibtorrentSessionInfoRequest(MockRequest): - """ - A MockRequest that mimics GetLibtorrentSessionInfoRequests. - """ - - def __init__(self, query: dict) -> None: - """ - Create a new GetLibtorrentSessionInfoRequest. - """ - super().__init__(query, "GET", "/libtorrent/session") class TestLibTorrentEndpoint(TestBase): @@ -51,8 +27,9 @@ async def test_get_settings_unknown_unspecified_hops_default(self) -> None: Test if getting settings for an unspecified number of hops defaults to 0 hops. """ self.download_manager.ltsessions = {} + request = MockRequest("/api/libtorrent/settings", query={}) - response = await self.endpoint.get_libtorrent_settings(GetLibtorrentSettingsRequest({})) + response = await self.endpoint.get_libtorrent_settings(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -64,8 +41,9 @@ async def test_get_settings_unknown_specified_hops_default(self) -> None: Test if getting settings for an unknown number of hops defaults to 0 hops. """ self.download_manager.ltsessions = {} + request = MockRequest("/api/libtorrent/settings", query={"hop": 1}) - response = await self.endpoint.get_libtorrent_settings(GetLibtorrentSettingsRequest({"hop": 1})) + response = await self.endpoint.get_libtorrent_settings(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -80,8 +58,9 @@ async def test_get_settings_zero_hops(self) -> None: fut.set_result(Mock()) self.download_manager.ltsessions = {0: fut} self.download_manager.get_session_settings = Mock(return_value={"peer_fingerprint": "test", "test": "test"}) + request = MockRequest("/api/libtorrent/settings", query={}) - response = await self.endpoint.get_libtorrent_settings(GetLibtorrentSettingsRequest({})) + response = await self.endpoint.get_libtorrent_settings(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -96,8 +75,9 @@ async def test_get_settings_more_hops(self) -> None: fut = Future() fut.set_result(Mock(get_settings=Mock(return_value={"test": "test"}))) self.download_manager.ltsessions = {2: fut} + request = MockRequest("/api/libtorrent/settings", query={"hop": 2}) - response = await self.endpoint.get_libtorrent_settings(GetLibtorrentSettingsRequest({"hop": 2})) + response = await self.endpoint.get_libtorrent_settings(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -109,8 +89,9 @@ async def test_get_session_info_unknown_unspecified_hops_default(self) -> None: Test if getting session info for an unspecified number of hops defaults to 0 hops. """ self.download_manager.ltsessions = {} + request = MockRequest("/api/libtorrent/settings") - response = await self.endpoint.get_libtorrent_session_info(GetLibtorrentSettingsRequest({})) + response = await self.endpoint.get_libtorrent_session_info(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -122,8 +103,9 @@ async def test_get_session_info_unknown_specified_hops_default(self) -> None: Test if getting session info for an unknown number of hops defaults to 0 hops. """ self.download_manager.ltsessions = {} + request = MockRequest("/api/libtorrent/settings", query={"hop": 1}) - response = await self.endpoint.get_libtorrent_session_info(GetLibtorrentSettingsRequest({"hop": 1})) + response = await self.endpoint.get_libtorrent_session_info(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -137,8 +119,9 @@ async def test_get_session_info_known(self) -> None: fut = Future() fut.set_result(Mock()) self.download_manager.ltsessions = {0: fut} + request = MockRequest("/api/libtorrent/settings", query={}) - response_future = ensure_future(self.endpoint.get_libtorrent_session_info(GetLibtorrentSettingsRequest({}))) + response_future = ensure_future(self.endpoint.get_libtorrent_session_info(request)) await sleep(0) self.download_manager.session_stats_callback(Mock(values={"test": "test"})) response = await response_future diff --git a/src/tribler/test_unit/core/libtorrent/restapi/test_torrentinfo_endpoint.py b/src/tribler/test_unit/core/libtorrent/restapi/test_torrentinfo_endpoint.py index 7d692fb857..8eba5aed63 100644 --- a/src/tribler/test_unit/core/libtorrent/restapi/test_torrentinfo_endpoint.py +++ b/src/tribler/test_unit/core/libtorrent/restapi/test_torrentinfo_endpoint.py @@ -1,11 +1,12 @@ import json -from asyncio import TimeoutError +from asyncio import TimeoutError as AsyncTimeoutError from binascii import unhexlify from ssl import SSLError from unittest.mock import AsyncMock, Mock, patch from aiohttp import ClientConnectorCertificateError, ClientConnectorError, ClientResponseError, ServerConnectionError from ipv8.test.base import TestBase +from ipv8.test.REST.rest_base import MockRequest, response_to_json from ipv8.util import succeed import tribler @@ -13,22 +14,9 @@ from tribler.core.libtorrent.restapi.torrentinfo_endpoint import TorrentInfoEndpoint, recursive_unicode from tribler.core.libtorrent.torrentdef import TorrentDef, TorrentDefNoMetainfo from tribler.core.restapi.rest_endpoint import HTTP_BAD_REQUEST, HTTP_INTERNAL_SERVER_ERROR -from tribler.test_unit.base_restapi import MockRequest, response_to_json from tribler.test_unit.core.libtorrent.mocks import TORRENT_WITH_DIRS_CONTENT -class GetTorrentInfoRequest(MockRequest): - """ - A MockRequest that mimics GetTorrentInfoRequests. - """ - - def __init__(self, query: dict) -> None: - """ - Create a new GetTorrentInfoRequest. - """ - super().__init__(query, "GET", "/torrentinfo") - - async def mock_unshorten(uri: str) -> str: """ Don't following links. @@ -54,7 +42,9 @@ async def test_get_torrent_info_bad_hops(self) -> None: """ Test if a graceful error is returned when the supplied number of hops is an int value. """ - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": "foo", "uri": "file://"})) + request = MockRequest("/api/torrentinfo", query={"hops": "foo", "uri": "file://"}) + + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -64,7 +54,9 @@ async def test_get_torrent_info_bad_scheme(self) -> None: """ Test if a graceful error is returned when the supplied the URI scheme is unknown. """ - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, "uri": "xxx://"})) + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "xxx://"}) + + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -74,9 +66,11 @@ async def test_get_torrent_info_no_metainfo(self) -> None: """ Test if a graceful error is returned when no metainfo is available for a file. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "file://"}) + tdef = TorrentDefNoMetainfo(b"\x01" * 20, b"test") with patch("tribler.core.libtorrent.torrentdef.TorrentDef.load", AsyncMock(return_value=tdef)): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, "uri": "file://"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -86,8 +80,10 @@ async def test_get_torrent_info_file_filenotfounderror(self) -> None: """ Test if a graceful error is returned when a FileNotFoundError occurs when loading a torrent. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "file://"}) + with patch("tribler.core.libtorrent.torrentdef.TorrentDef.load", AsyncMock(side_effect=FileNotFoundError)): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, "uri": "file://"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -97,8 +93,10 @@ async def test_get_torrent_info_file_typeerror(self) -> None: """ Test if a graceful error is returned when a TypeError occurs when loading a torrent. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "file://"}) + with patch("tribler.core.libtorrent.torrentdef.TorrentDef.load", AsyncMock(side_effect=TypeError)): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, "uri": "file://"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -108,8 +106,10 @@ async def test_get_torrent_info_file_valueerror(self) -> None: """ Test if a graceful error is returned when a ValueError occurs when loading a torrent. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "file://"}) + with patch("tribler.core.libtorrent.torrentdef.TorrentDef.load", AsyncMock(side_effect=ValueError)): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, "uri": "file://"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -119,8 +119,10 @@ async def test_get_torrent_info_file_runtimeerror(self) -> None: """ Test if a graceful error is returned when a RuntimeError occurs when loading a torrent. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "file://"}) + with patch("tribler.core.libtorrent.torrentdef.TorrentDef.load", AsyncMock(side_effect=RuntimeError)): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, "uri": "file://"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -130,9 +132,11 @@ async def test_get_torrent_info_magnet_runtimeerror_compat(self) -> None: """ Test if a graceful error is returned when a RuntimeError occurs when loading a magnet in compatibility mode. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "magnet://"}) + with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"lt": Mock(parse_magnet_uri=Mock(side_effect=RuntimeError))}): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, "uri": "magnet://"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -143,12 +147,14 @@ async def test_get_torrent_info_magnet_runtimeerror_modern(self) -> None: """ Test if a graceful error is returned when a RuntimeError occurs when loading a magnet. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "magnet://"}) + with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"lt": Mock(parse_magnet_uri=type("test", (object, ), { "info_hash": property(Mock(side_effect=RuntimeError)), "__init__": lambda _, __: None }))}): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, "uri": "magnet://"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -160,10 +166,11 @@ async def test_get_torrent_info_magnet_no_metainfo(self) -> None: Test if a graceful error is returned when no metainfo is available for a magnet. """ self.download_manager.get_metainfo = AsyncMock(return_value=None) + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "magnet://"}) with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"lt": Mock(parse_magnet_uri=Mock(return_value={"info_hash": b"\x01" * 20}))}): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, "uri": "magnet://"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -177,12 +184,13 @@ async def test_get_torrent_info_http_serverconnectionerror(self) -> None: """ Test if a graceful error is returned when a ServerConnectionError occurs when loading from an HTTP link. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "http://127.0.0.1/file"}) + with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"unshorten": mock_unshorten}), \ patch("tribler.core.libtorrent.restapi.torrentinfo_endpoint.query_uri", AsyncMock(side_effect=ServerConnectionError("test"))): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, - "uri": "http://127.0.0.1/file"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -192,12 +200,13 @@ async def test_get_torrent_info_http_clientresponseerror(self) -> None: """ Test if a graceful error is returned when a ClientResponseError occurs when loading from an HTTP link. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "http://127.0.0.1/file"}) + with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"unshorten": mock_unshorten}), \ patch("tribler.core.libtorrent.restapi.torrentinfo_endpoint.query_uri", AsyncMock(side_effect=ClientResponseError(Mock(real_url="test"), ()))): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, - "uri": "http://127.0.0.1/file"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -207,12 +216,13 @@ async def test_get_torrent_info_http_sslerror(self) -> None: """ Test if a graceful error is returned when a SSLError occurs when loading from an HTTP link. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "http://127.0.0.1/file"}) + with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"unshorten": mock_unshorten}), \ patch("tribler.core.libtorrent.restapi.torrentinfo_endpoint.query_uri", AsyncMock(side_effect=SSLError("test"))): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, - "uri": "http://127.0.0.1/file"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -222,13 +232,14 @@ async def test_get_torrent_info_http_clientconnectorerror(self) -> None: """ Test if a graceful error is returned when a ClientConnectorError occurs when loading from an HTTP link. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "http://127.0.0.1/file"}) + with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"unshorten": mock_unshorten}), \ patch("tribler.core.libtorrent.restapi.torrentinfo_endpoint.query_uri", AsyncMock(side_effect=ClientConnectorError(Mock(ssl="default", host="test", port=42), OSError("test")))): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, - "uri": "http://127.0.0.1/file"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -238,12 +249,13 @@ async def test_get_torrent_info_http_timeouterror(self) -> None: """ Test if a graceful error is returned when a TimeoutError occurs when loading from an HTTP link. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "http://127.0.0.1/file"}) + with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"unshorten": mock_unshorten}), \ patch("tribler.core.libtorrent.restapi.torrentinfo_endpoint.query_uri", - AsyncMock(side_effect=TimeoutError("test"))): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, - "uri": "http://127.0.0.1/file"})) + AsyncMock(side_effect=AsyncTimeoutError("test"))): + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -253,12 +265,13 @@ async def test_get_torrent_info_http_valueerror(self) -> None: """ Test if a graceful error is returned when a ValueError occurs when loading from an HTTP link. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "http://127.0.0.1/file"}) + with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"unshorten": mock_unshorten}), \ patch("tribler.core.libtorrent.restapi.torrentinfo_endpoint.query_uri", AsyncMock(side_effect=ValueError("test"))): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, - "uri": "http://127.0.0.1/file"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -268,12 +281,13 @@ async def test_get_torrent_info_https_serverconnectionerror(self) -> None: """ Test if a graceful error is returned when a ServerConnectionError occurs when loading from an HTTPS link. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "https://127.0.0.1/file"}) + with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"unshorten": mock_unshorten}), \ patch("tribler.core.libtorrent.restapi.torrentinfo_endpoint.query_uri", AsyncMock(side_effect=ServerConnectionError("test"))): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, - "uri": "https://127.0.0.1/file"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -283,12 +297,13 @@ async def test_get_torrent_info_https_clientresponseerror(self) -> None: """ Test if a graceful error is returned when a ClientResponseError occurs when loading from an HTTPS link. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "https://127.0.0.1/file"}) + with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"unshorten": mock_unshorten}), \ patch("tribler.core.libtorrent.restapi.torrentinfo_endpoint.query_uri", AsyncMock(side_effect=ClientResponseError(Mock(real_url="test"), ()))): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, - "uri": "https://127.0.0.1/file"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -298,12 +313,13 @@ async def test_get_torrent_info_https_sslerror(self) -> None: """ Test if a graceful error is returned when a SSLError occurs when loading from an HTTPS link. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "https://127.0.0.1/file"}) + with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"unshorten": mock_unshorten}), \ patch("tribler.core.libtorrent.restapi.torrentinfo_endpoint.query_uri", AsyncMock(side_effect=SSLError("test"))): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, - "uri": "https://127.0.0.1/file"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -313,13 +329,14 @@ async def test_get_torrent_info_https_clientconnectorerror(self) -> None: """ Test if a graceful error is returned when a ClientConnectorError occurs when loading from an HTTPS link. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "https://127.0.0.1/file"}) + with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"unshorten": mock_unshorten}), \ patch("tribler.core.libtorrent.restapi.torrentinfo_endpoint.query_uri", AsyncMock(side_effect=ClientConnectorError(Mock(ssl="default", host="test", port=42), OSError("test")))): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, - "uri": "https://127.0.0.1/file"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -329,12 +346,13 @@ async def test_get_torrent_info_https_timeouterror(self) -> None: """ Test if a graceful error is returned when a TimeoutError occurs when loading from an HTTPS link. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "https://127.0.0.1/file"}) + with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"unshorten": mock_unshorten}), \ patch("tribler.core.libtorrent.restapi.torrentinfo_endpoint.query_uri", - AsyncMock(side_effect=TimeoutError("test"))): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, - "uri": "https://127.0.0.1/file"})) + AsyncMock(side_effect=AsyncTimeoutError("test"))): + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -344,12 +362,13 @@ async def test_get_torrent_info_https_valueerror(self) -> None: """ Test if a graceful error is returned when a ValueError occurs when loading from an HTTPS link. """ + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "https://127.0.0.1/file"}) + with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"unshorten": mock_unshorten}), \ patch("tribler.core.libtorrent.restapi.torrentinfo_endpoint.query_uri", AsyncMock(side_effect=ValueError("test"))): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, - "uri": "https://127.0.0.1/file"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -366,12 +385,14 @@ async def server_response(_: str, valid_cert: bool = True) -> bytes: if valid_cert: raise ClientConnectorCertificateError(None, RuntimeError("Invalid certificate test error!")) return await succeed(b"d4:infod6:lengthi0eee") + + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "https://127.0.0.1/file"}) + with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"unshorten": mock_unshorten}), \ patch("tribler.core.libtorrent.restapi.torrentinfo_endpoint.query_uri", server_response): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, - "uri": "https://127.0.0.1/file"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(200, response.status) @@ -382,12 +403,12 @@ async def test_get_torrent_info_http_no_metainfo(self) -> None: Test if a graceful error is returned when no metainfo is available for a http link. """ self.download_manager.get_metainfo = AsyncMock(return_value=None) + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "https://127.0.0.1/file"}) with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"unshorten": mock_unshorten}), \ patch("tribler.core.libtorrent.restapi.torrentinfo_endpoint.query_uri", AsyncMock(return_value=b"de")): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, - "uri": "http://127.0.0.1/file"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -398,12 +419,12 @@ async def test_get_torrent_info_https_no_metainfo(self) -> None: Test if a graceful error is returned when no metainfo is available for a https link. """ self.download_manager.get_metainfo = AsyncMock(return_value=None) + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "https://127.0.0.1/file"}) with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"unshorten": mock_unshorten}), \ patch("tribler.core.libtorrent.restapi.torrentinfo_endpoint.query_uri", AsyncMock(return_value=b"de")): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, - "uri": "https://127.0.0.1/file"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -414,6 +435,7 @@ async def test_get_torrent_info_http_redirect_magnet_no_metainfo(self) -> None: Test if a graceful error is returned when no metainfo is available for a magnet returned by a HTTP link. """ self.download_manager.get_metainfo = AsyncMock(return_value=None) + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "https://127.0.0.1/file"}) with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"unshorten": mock_unshorten}), \ @@ -421,8 +443,7 @@ async def test_get_torrent_info_http_redirect_magnet_no_metainfo(self) -> None: AsyncMock(return_value=b"magnet://")), \ patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"lt": Mock(parse_magnet_uri=Mock(return_value={"info_hash": b"\x01" * 20}))}): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, - "uri": "http://127.0.0.1/file"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -437,6 +458,7 @@ async def test_get_torrent_info_https_redirect_magnet_no_metainfo(self) -> None: Test if a graceful error is returned when no metainfo is available for a magnet returned by a HTTPS link. """ self.download_manager.get_metainfo = AsyncMock(return_value=None) + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "https://127.0.0.1/file"}) with patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"unshorten": mock_unshorten}), \ @@ -444,8 +466,7 @@ async def test_get_torrent_info_https_redirect_magnet_no_metainfo(self) -> None: AsyncMock(return_value=b"magnet://")), \ patch.dict(tribler.core.libtorrent.restapi.torrentinfo_endpoint.__dict__, {"lt": Mock(parse_magnet_uri=Mock(return_value={"info_hash": b"\x01" * 20}))}): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, - "uri": "https://127.0.0.1/file"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -461,8 +482,10 @@ async def test_get_torrent_info_invalid_response_empty_metainfo(self) -> None: """ tdef = TorrentDef().load_from_memory(TORRENT_WITH_DIRS_CONTENT) tdef.metainfo = 3 + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "file://"}) + with patch("tribler.core.libtorrent.torrentdef.TorrentDef.load", AsyncMock(return_value=tdef)): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, "uri": "file://"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -474,8 +497,10 @@ async def test_get_torrent_info_invalid_response_empty_info(self) -> None: """ tdef = TorrentDef().load_from_memory(TORRENT_WITH_DIRS_CONTENT) tdef.metainfo.pop(b"info") + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "file://"}) + with patch("tribler.core.libtorrent.torrentdef.TorrentDef.load", AsyncMock(return_value=tdef)): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, "uri": "file://"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) self.assertEqual(HTTP_INTERNAL_SERVER_ERROR, response.status) @@ -487,8 +512,10 @@ async def test_get_torrent_info_valid_download(self) -> None: """ tdef = TorrentDef().load_from_memory(TORRENT_WITH_DIRS_CONTENT) self.download_manager.metainfo_requests = {} + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "file://"}) + with patch("tribler.core.libtorrent.torrentdef.TorrentDef.load", AsyncMock(return_value=tdef)): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, "uri": "file://"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) response_info_json = json.loads(unhexlify(response_body_json["metainfo"])) @@ -507,8 +534,10 @@ async def test_get_torrent_info_valid_metainfo_request(self) -> None: tdef = TorrentDef().load_from_memory(TORRENT_WITH_DIRS_CONTENT) download = self.download_manager.downloads.get(tdef.infohash) self.download_manager.metainfo_requests = {tdef.infohash: MetainfoLookup(download, 1)} + request = MockRequest("/api/torrentinfo", query={"hops": 0, "uri": "file://"}) + with patch("tribler.core.libtorrent.torrentdef.TorrentDef.load", AsyncMock(return_value=tdef)): - response = await self.endpoint.get_torrent_info(GetTorrentInfoRequest({"hops": 0, "uri": "file://"})) + response = await self.endpoint.get_torrent_info(request) response_body_json = await response_to_json(response) response_info_json = json.loads(unhexlify(response_body_json["metainfo"])) diff --git a/src/tribler/test_unit/core/restapi/test_events_endpoint.py b/src/tribler/test_unit/core/restapi/test_events_endpoint.py index 6a9ca9502e..3d220b0834 100644 --- a/src/tribler/test_unit/core/restapi/test_events_endpoint.py +++ b/src/tribler/test_unit/core/restapi/test_events_endpoint.py @@ -2,11 +2,11 @@ from aiohttp.abc import AbstractStreamWriter from ipv8.test.base import TestBase +from ipv8.test.REST.rest_base import MockRequest from multidict import CIMultiDict from tribler.core.notifier import Notification, Notifier from tribler.core.restapi.events_endpoint import EventsEndpoint -from tribler.test_unit.base_restapi import MockRequest class GetEventsRequest(MockRequest): @@ -20,7 +20,7 @@ def __init__(self, endpoint: EventsEndpoint, count: int = 1) -> None: """ self.payload_writer = MockStreamWriter(endpoint, count=count) self._handler_waiter = Future() - super().__init__({}, "GET", "/api/events", payload_writer=self.payload_writer) + super().__init__("/api/events", payload_writer=self.payload_writer) def shutdown(self) -> None: """ diff --git a/src/tribler/test_unit/core/restapi/test_ipv8_endpoint.py b/src/tribler/test_unit/core/restapi/test_ipv8_endpoint.py index 3909d2b28a..db2b1199f9 100644 --- a/src/tribler/test_unit/core/restapi/test_ipv8_endpoint.py +++ b/src/tribler/test_unit/core/restapi/test_ipv8_endpoint.py @@ -17,7 +17,6 @@ def test_binding(self) -> None: self.assertEqual("/api/ipv8", endpoint.path) self.assertIn("/asyncio", endpoint.endpoints) - self.assertIn("/attestation", endpoint.endpoints) self.assertIn("/dht", endpoint.endpoints) self.assertIn("/identity", endpoint.endpoints) self.assertIn("/isolation", endpoint.endpoints) diff --git a/src/tribler/test_unit/core/restapi/test_rest_endpoint.py b/src/tribler/test_unit/core/restapi/test_rest_endpoint.py index 1af9dc3a53..1c3d669392 100644 --- a/src/tribler/test_unit/core/restapi/test_rest_endpoint.py +++ b/src/tribler/test_unit/core/restapi/test_rest_endpoint.py @@ -1,3 +1,4 @@ +from ipv8.test.REST.rest_base import response_to_bytes, response_to_json from ipv8.test.base import TestBase from tribler.core.restapi.rest_endpoint import ( @@ -8,7 +9,6 @@ return_handled_exception, ) from tribler.core.restapi.rest_manager import error_middleware -from tribler.test_unit.base_restapi import response_to_bytes, response_to_json class TestRESTEndpoint(TestBase): diff --git a/src/tribler/test_unit/core/restapi/test_rest_manager.py b/src/tribler/test_unit/core/restapi/test_rest_manager.py index dc0a77c024..ceb1aab35f 100644 --- a/src/tribler/test_unit/core/restapi/test_rest_manager.py +++ b/src/tribler/test_unit/core/restapi/test_rest_manager.py @@ -6,6 +6,7 @@ from aiohttp import hdrs, web from aiohttp.web_exceptions import HTTPNotFound, HTTPRequestEntityTooLarge from ipv8.test.base import TestBase +from ipv8.test.REST.rest_base import MockRequest, response_to_json from tribler.core.restapi.rest_endpoint import ( HTTP_INTERNAL_SERVER_ERROR, @@ -16,7 +17,6 @@ RESTResponse, ) from tribler.core.restapi.rest_manager import ApiKeyMiddleware, RESTManager, error_middleware -from tribler.test_unit.base_restapi import MockRequest, response_to_json from tribler.test_unit.mocks import MockTriblerConfigManager if TYPE_CHECKING: @@ -33,7 +33,7 @@ def __init__(self, path: str = "", query: dict | None = None, headers: dict | No """ Create a new GenericRequest. """ - super().__init__(query or {}, path=path) + super().__init__(path, "GET", query) self._headers = headers or {} if cookies is not None: self._headers[hdrs.COOKIE] = BaseCookie(cookies) diff --git a/src/tribler/test_unit/core/restapi/test_settings_endpoint.py b/src/tribler/test_unit/core/restapi/test_settings_endpoint.py index 8e027ef6e2..04437454b1 100644 --- a/src/tribler/test_unit/core/restapi/test_settings_endpoint.py +++ b/src/tribler/test_unit/core/restapi/test_settings_endpoint.py @@ -1,24 +1,12 @@ from unittest.mock import Mock, call from ipv8.test.base import TestBase +from ipv8.test.REST.rest_base import MockRequest, response_to_json from tribler.core.restapi.settings_endpoint import SettingsEndpoint -from tribler.test_unit.base_restapi import MockRequest, response_to_json from tribler.test_unit.mocks import MockTriblerConfigManager -class GetSettingsRequest(MockRequest): - """ - A MockRequest that mimics GetSettingsRequests. - """ - - def __init__(self) -> None: - """ - Create a new GetSettingsRequest. - """ - super().__init__({}, "GET", "/settings") - - class UpdateSettingsRequest(MockRequest): """ A MockRequest that mimics UpdateSettingsRequests. @@ -28,7 +16,7 @@ def __init__(self, raw_json_content: bytes) -> None: """ Create a new UpdateSettingsRequest. """ - super().__init__({}, "POST", "/settings") + super().__init__("/api/settings", "POST") self.raw_json_content = raw_json_content async def read(self) -> bytes: @@ -50,8 +38,9 @@ async def test_get_settings(self) -> None: config = MockTriblerConfigManager() config.set("api/http_port", 1337) endpoint = SettingsEndpoint(config) + request = MockRequest("/api/settings") - response = await endpoint.get_settings(GetSettingsRequest()) + response = await endpoint.get_settings(request) response_body_json = await response_to_json(response) self.assertEqual(1337, response_body_json["settings"]["api"]["http_port"]) diff --git a/src/tribler/test_unit/core/restapi/test_shutdown_endpoint.py b/src/tribler/test_unit/core/restapi/test_shutdown_endpoint.py index 67c859f549..e912fb924a 100644 --- a/src/tribler/test_unit/core/restapi/test_shutdown_endpoint.py +++ b/src/tribler/test_unit/core/restapi/test_shutdown_endpoint.py @@ -1,19 +1,7 @@ from ipv8.test.base import TestBase +from ipv8.test.REST.rest_base import MockRequest, response_to_json from tribler.core.restapi.shutdown_endpoint import ShutdownEndpoint -from tribler.test_unit.base_restapi import MockRequest, response_to_json - - -class ShutdownRequest(MockRequest): - """ - A MockRequest that mimics ShutdownRequests. - """ - - def __init__(self) -> None: - """ - Create a new ShutdownRequest. - """ - super().__init__({}, "PUT", "/shutdown") class TestShutdownEndpoint(TestBase): @@ -27,8 +15,9 @@ async def test_shutdown(self) -> None: """ value = [2, 1] endpoint = ShutdownEndpoint(value.reverse) + request = MockRequest("/api/shutdown", "PUT") - response = endpoint.shutdown_request(ShutdownRequest()) + response = endpoint.shutdown_request(request) response_body_json = await response_to_json(response) self.assertTrue(response_body_json["shutdown"]) diff --git a/src/tribler/test_unit/core/restapi/test_statistics_endpoint.py b/src/tribler/test_unit/core/restapi/test_statistics_endpoint.py index f279d2c51a..b86e180892 100644 --- a/src/tribler/test_unit/core/restapi/test_statistics_endpoint.py +++ b/src/tribler/test_unit/core/restapi/test_statistics_endpoint.py @@ -1,33 +1,9 @@ from unittest.mock import Mock from ipv8.test.base import TestBase +from ipv8.test.REST.rest_base import MockRequest, response_to_json from tribler.core.restapi.statistics_endpoint import StatisticsEndpoint -from tribler.test_unit.base_restapi import MockRequest, response_to_json - - -class TriblerStatsRequest(MockRequest): - """ - A MockRequest that mimics TriblerStatsRequests. - """ - - def __init__(self) -> None: - """ - Create a new TriblerStatsRequest. - """ - super().__init__({}, "GET", "/statistics/tribler") - - -class IPv8StatsRequest(MockRequest): - """ - A MockRequest that mimics IPv8StatsRequests. - """ - - def __init__(self) -> None: - """ - Create a new IPv8StatsRequest. - """ - super().__init__({}, "GET", "/statistics/ipv8") class TestStatisticsEndpoint(TestBase): @@ -40,8 +16,9 @@ async def test_get_tribler_stats_no_mds(self) -> None: Test if getting Tribler stats without a MetadataStore gives empty Tribler statistics. """ endpoint = StatisticsEndpoint() + request = MockRequest("/api/statistics/tribler") - response = endpoint.get_tribler_stats(TriblerStatsRequest()) + response = endpoint.get_tribler_stats(request) response_body_json = await response_to_json(response) self.assertEqual({}, response_body_json["tribler_statistics"]) @@ -52,8 +29,9 @@ async def test_get_tribler_stats_with_mds(self) -> None: """ endpoint = StatisticsEndpoint() endpoint.mds = Mock(get_db_file_size=Mock(return_value=42), get_num_torrents=Mock(return_value=7)) + request = MockRequest("/api/statistics/tribler") - response = endpoint.get_tribler_stats(TriblerStatsRequest()) + response = endpoint.get_tribler_stats(request) response_body_json = await response_to_json(response) self.assertEqual(42, response_body_json["tribler_statistics"]["db_size"]) @@ -64,8 +42,9 @@ async def test_get_ipv8_stats_no_ipv8(self) -> None: Test if getting IPv8 stats without IPv8 gives empty IPv8 statistics. """ endpoint = StatisticsEndpoint() + request = MockRequest("/api/statistics/ipv8") - response = endpoint.get_ipv8_stats(IPv8StatsRequest()) + response = endpoint.get_ipv8_stats(request) response_body_json = await response_to_json(response) self.assertEqual({}, response_body_json["ipv8_statistics"]) @@ -76,8 +55,9 @@ async def test_get_ipv8_stats_with_ipv8(self) -> None: """ endpoint = StatisticsEndpoint() endpoint.ipv8 = Mock(endpoint=Mock(bytes_up=7, bytes_down=42)) + request = MockRequest("/api/statistics/ipv8") - response = endpoint.get_ipv8_stats(IPv8StatsRequest()) + response = endpoint.get_ipv8_stats(request) response_body_json = await response_to_json(response) self.assertEqual(42, response_body_json["ipv8_statistics"]["total_down"]) diff --git a/src/tribler/test_unit/core/versioning/restapi/test_versioning_endpoint.py b/src/tribler/test_unit/core/versioning/restapi/test_versioning_endpoint.py index e22e1a402d..851b4b2471 100644 --- a/src/tribler/test_unit/core/versioning/restapi/test_versioning_endpoint.py +++ b/src/tribler/test_unit/core/versioning/restapi/test_versioning_endpoint.py @@ -1,65 +1,14 @@ from __future__ import annotations -from typing import TYPE_CHECKING from unittest.mock import AsyncMock, Mock, call from ipv8.test.base import TestBase +from ipv8.test.REST.rest_base import MockRequest, response_to_json from tribler.core.restapi.rest_endpoint import HTTP_BAD_REQUEST from tribler.core.versioning.restapi.versioning_endpoint import VersioningEndpoint -from tribler.test_unit.base_restapi import MockRequest, response_to_json from tribler.tribler_config import VERSION_SUBDIR -if TYPE_CHECKING: - from tribler.core.versioning.manager import VersioningManager - - -class GenericRequest(MockRequest): - """ - A MockRequest that mimics generic GET requests for the versioning endpoint. - """ - - def __init__(self, vman: VersioningManager, route: str) -> None: - """ - Create a new request. - """ - super().__init__({}, "GET", f"/versioning/{route}") - self.context = (vman,) - - -class PerformUpgradeRequest(MockRequest): - """ - A MockRequest that mimics PerformUpgrade requests for the versioning endpoint. - """ - - def __init__(self, vman: VersioningManager) -> None: - """ - Create a new request. - """ - super().__init__({}, "POST", "/versioning/upgrade") - self.context = (vman,) - - -class RemoveVersionRequest(MockRequest): - """ - A MockRequest that mimics RemoveVersion requests for the versioning endpoint. - """ - - def __init__(self, vman: VersioningManager, version: str) -> None: - """ - Create a new request. - """ - super().__init__({}, "DELETE", f"/versioning/versions/{version}") - self.context = (vman,) - self.version_str = version - - @property - def match_info(self) -> dict[str, str]: - """ - Return our version info. - """ - return {"version": self.version_str} - class TestVersioningEndpoint(TestBase): """ @@ -80,8 +29,10 @@ async def test_current_version(self) -> None: Check if the current version is correctly returned. """ self.vman.get_current_version = Mock(return_value="1.2.3") + request = MockRequest("/api/versioning/versions/current", match_info={"route": "versions/current"}) + request.context = [self.vman] - response = await self.rest_ep.get_current_version(GenericRequest(self.vman, "versions/current")) + response = await self.rest_ep.get_current_version(request) response_body_json = await response_to_json(response) self.assertEqual("1.2.3", response_body_json["version"]) @@ -91,8 +42,10 @@ async def test_versions(self) -> None: Check if the known versions are correctly returned. """ self.vman.get_versions = Mock(return_value=["1.2.3", "4.5.6"]) + request = MockRequest("/api/versioning/versions", match_info={"route": "versions"}) + request.context = [self.vman] - response = await self.rest_ep.get_versions(GenericRequest(self.vman, "versions")) + response = await self.rest_ep.get_versions(request) response_body_json = await response_to_json(response) self.assertEqual({"1.2.3", "4.5.6"}, set(response_body_json["versions"])) @@ -103,8 +56,10 @@ async def test_check_version_available(self) -> None: Check if the checked version is correctly returned when a version is available. """ self.vman.check_version = AsyncMock(return_value="1.2.3") + request = MockRequest("/api/versioning/versions/check", match_info={"route": "versions/check"}) + request.context = [self.vman] - response = await self.rest_ep.check_version(GenericRequest(self.vman, "versions/check")) + response = await self.rest_ep.check_version(request) response_body_json = await response_to_json(response) self.assertTrue(response_body_json["has_version"]) @@ -115,8 +70,10 @@ async def test_check_version_unavailable(self) -> None: Check if the checked version is correctly returned when a version is not available. """ self.vman.check_version = AsyncMock(return_value=None) + request = MockRequest("/api/versioning/versions/check", match_info={"route": "versions/check"}) + request.context = [self.vman] - response = await self.rest_ep.check_version(GenericRequest(self.vman, "versions/check")) + response = await self.rest_ep.check_version(request) response_body_json = await response_to_json(response) self.assertFalse(response_body_json["has_version"]) @@ -127,8 +84,10 @@ async def test_can_upgrade_no(self) -> None: Check if the inability to upgrade is correctly returned. """ self.vman.can_upgrade = Mock(return_value=False) + request = MockRequest("/api/versioning/upgrade/available", match_info={"route": "upgrade/available"}) + request.context = [self.vman] - response = await self.rest_ep.can_upgrade(GenericRequest(self.vman, "upgrade/available")) + response = await self.rest_ep.can_upgrade(request) response_body_json = await response_to_json(response) self.assertFalse(response_body_json["can_upgrade"]) @@ -138,8 +97,10 @@ async def test_can_upgrade(self) -> None: Check if the ability to upgrade is correctly returned. """ self.vman.can_upgrade = Mock(return_value="1.2.3") + request = MockRequest("/api/versioning/upgrade/available", match_info={"route": "upgrade/available"}) + request.context = [self.vman] - response = await self.rest_ep.can_upgrade(GenericRequest(self.vman, "upgrade/available")) + response = await self.rest_ep.can_upgrade(request) response_body_json = await response_to_json(response) self.assertEqual("1.2.3", response_body_json["can_upgrade"]) @@ -149,8 +110,10 @@ async def test_is_upgrading(self) -> None: Check if the upgrading status is correctly returned. """ self.vman.task_manager.get_task = Mock(return_value=True) + request = MockRequest("/api/versioning/upgrade/available", match_info={"route": "upgrade/working"}) + request.context = [self.vman] - response = await self.rest_ep.is_upgrading(GenericRequest(self.vman, "upgrade/working")) + response = await self.rest_ep.is_upgrading(request) response_body_json = await response_to_json(response) self.assertTrue(response_body_json["running"]) @@ -160,8 +123,10 @@ async def test_is_upgrading_no(self) -> None: Check if the non-upgrading status is correctly returned. """ self.vman.task_manager.get_task = Mock(return_value=None) + request = MockRequest("/api/versioning/upgrade/available", match_info={"route": "upgrade/working"}) + request.context = [self.vman] - response = await self.rest_ep.is_upgrading(GenericRequest(self.vman, "upgrade/working")) + response = await self.rest_ep.is_upgrading(request) response_body_json = await response_to_json(response) self.assertFalse(response_body_json["running"]) @@ -170,7 +135,10 @@ async def test_perform_upgrade(self) -> None: """ Check if a request to perform an upgrade launches an upgrade task. """ - response = await self.rest_ep.perform_upgrade(PerformUpgradeRequest(self.vman)) + request = MockRequest("/api/versioning/upgrade", "POST") + request.context = [self.vman] + + response = await self.rest_ep.perform_upgrade(request) response_body_json = await response_to_json(response) self.assertTrue(response_body_json["success"]) @@ -180,7 +148,10 @@ async def test_remove_version_illegal(self) -> None: """ Check if a request without a version returns a BAD REQUEST status. """ - response = await self.rest_ep.remove_version(RemoveVersionRequest(self.vman, "")) + request = MockRequest("/api/versioning/versions/", "POST", {}, {"version": ""}) + request.context = [self.vman] + + response = await self.rest_ep.remove_version(request) self.assertEqual(HTTP_BAD_REQUEST, response.status) @@ -188,7 +159,10 @@ async def test_remove_version(self) -> None: """ Check if a request to remove a given version is forwarded. """ - response = await self.rest_ep.remove_version(RemoveVersionRequest(self.vman, "1.2.3")) + request = MockRequest("/api/versioning/versions/1.2.3", "POST", {}, {"version": "1.2.3"}) + request.context = [self.vman] + + response = await self.rest_ep.remove_version(request) response_body_json = await response_to_json(response) self.assertTrue(response_body_json["success"])