Skip to content

Commit

Permalink
update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rmartin16 committed Apr 11, 2021
1 parent 9c0e857 commit 679e130
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 35 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
env:
LATEST_PYTHON_VERSION: 3.9
LATEST_QBT_VERSION: 4.3.4.1
QBT_ALWAYS_TEST: 4.3.4.1, 4.3.3, 4.3.2
QBT_ALWAYS_TEST: 4.3.4.1, 4.3.3, 4.3.2, 4.3.1
SUBMIT_COVERAGE_VERSIONS: 2.7, 3.9
COMPREHENSIVE_TESTS_BRANCH: comprehensive_tests
PYTHON_QBITTORRENTAPI_HOST: localhost:8080
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Version 2021.4.20 (9 apr 2021)
Version 2021.4.20 (11 apr 2021)
- Add support for ratio limit and seeding time limit when adding torrents

Version 2021.4.19 (8 apr 2021)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import qbittorrentapi
qbt_client = qbittorrentapi.Client(host='localhost', port=8080, username='admin', password='adminadmin')

# the Client will automatically acquire/maintain a logged in state in line with any request.
# therefore, this is not necessary; however, you many want to test the provided login credentials.
# therefore, this is not necessary; however, you may want to test the provided login credentials.
try:
qbt_client.auth_log_in()
except qbittorrentapi.LoginFailed as e:
Expand Down
42 changes: 34 additions & 8 deletions qbittorrentapi/torrents.py
Original file line number Diff line number Diff line change
Expand Up @@ -1071,14 +1071,22 @@ def torrents_add(
:return: "Ok." for success and "Fails." for failure
"""

# convert pre-v2.7 params to post-v2.7 params if a newer qBittorrent is being used
# convert pre-v2.7 params to post-v2.7 params...or post-v2.7 to pre-v.2.7
api_version = self.app_web_api_version()
if (
content_layout is None
and is_root_folder is not None
and self._is_version_less_than("2.7", self.app_web_api_version(), lteq=True)
and self._is_version_less_than("2.7", api_version, lteq=True)
):
content_layout = "Original" if is_root_folder else "NoSubfolder"
is_root_folder = None
elif (
content_layout is not None
and is_root_folder is None
and self._is_version_less_than(api_version, "2.7", lteq=False)
):
is_root_folder = content_layout in {"Subfolder", "Original"}
content_layout = None

data = {
"urls": (None, self._list2string(urls, "\n")),
Expand Down Expand Up @@ -1421,23 +1429,41 @@ def torrents_rename_file(
"""
torrent_hash = torrent_hash

# convert pre-v2.7 params to post-v2.7 params if a newer qBittorrent is being used
# convert pre-v2.7 params to post-v2.7...or post-v2.7 to pre-v2.7
# HACK: v4.3.2 and v4.3.3 both use web api v2.7 but old/new_path were introduced in v4.3.3
if (
old_path is None
and new_path is None
and isinstance(file_id, int)
and self._is_version_less_than("v4.3.3", self.app.version, lteq=True)
and file_id is not None
and self._is_version_less_than("v4.3.3", self.app_version(), lteq=True)
):
try:
old_path = self.torrents_files(torrent_hash=torrent_hash)[file_id].name
except (IndexError, AttributeError):
except (IndexError, AttributeError, TypeError):
logger.debug(
"ERROR: File ID '%s' isn't valid...'oldPath' cannot be determined."
% file_id
"ERROR: File ID '%s' isn't valid...'oldPath' cannot be determined.",
file_id,
)
old_path = ""
new_path = new_file_name or ""
elif (
old_path is not None
and new_path is not None
and file_id is None
and self._is_version_less_than(self.app_version(), "v4.3.3", lteq=False)
):
# previous only allowed renaming the file...not also moving it
new_file_name = new_path.split("/")[-1]
for file in self.torrents_files(torrent_hash=torrent_hash):
if file.name == old_path:
file_id = file.id
break
else:
logger.debug(
"ERROR: old_path '%s' isn't valid...'file_id' cannot be determined.",
old_path,
)
file_id = ""

data = {
"hash": torrent_hash,
Expand Down
40 changes: 28 additions & 12 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from os import environ
from os import path
from os import path as os_path
from sys import path as sys_path
from time import sleep

import pytest
Expand Down Expand Up @@ -44,6 +45,11 @@
)
_orig_torrent_hash = "d1101a2b9d202811a05e8c57c557a20bf974dc8a"

with open(
os_path.join(sys_path[0], "tests", "kubuntu-20.04.2.0-desktop-amd64.iso.torrent"),
mode="rb",
) as f:
torrent1_file = f.read()
torrent1_url = "http://cdimage.ubuntu.com/kubuntu/releases/20.04.1/release/kubuntu-20.04.2.0-desktop-amd64.iso.torrent"
torrent1_filename = torrent1_url.split("/")[-1]
torrent1_hash = "2ea1327a1758400827fe091a9bb2a35dee9ea5e8"
Expand All @@ -52,6 +58,10 @@
torrent2_filename = torrent2_url.split("/")[-1]
torrent2_hash = "3d75247029ffa408e52714d371b6c0f15a63ff41"

with open(os_path.join(sys_path[0], "tests", "root_folder.torrent"), mode="rb") as f:
root_folder_torrent_file = f.read()
root_folder_torrent_hash = "a14553bd936a6d496402082454a70ea7a9521adc"

is_version_less_than = Request._is_version_less_than
suppress_context = Request._suppress_context

Expand Down Expand Up @@ -200,23 +210,29 @@ def orig_torrent(client, orig_torrent_hash):
@pytest.fixture
def new_torrent(client):
"""Torrent that is added on demand to qBittorrent and then removed"""
yield next(new_torrent_standalone(client))


def new_torrent_standalone(client, torrent_hash=torrent1_hash, **kwargs):
def add_test_torrent(client):
for attempt in range(_check_limit):
client.torrents.add(
urls=torrent1_url,
save_path=path.expanduser("~/test_download/"),
category="test_category",
is_paused=True,
upload_limit=1024,
download_limit=2048,
is_sequential_download=True,
is_first_last_piece_priority=True,
)
if kwargs:
client.torrents.add(**kwargs)
else:
client.torrents.add(
torrent_files=torrent1_file,
save_path=os_path.expanduser("~/test_download/"),
category="test_category",
is_paused=True,
upload_limit=1024,
download_limit=2048,
is_sequential_download=True,
is_first_last_piece_priority=True,
)
try:
# not all versions of torrents_info() support passing a hash
return list(
filter(lambda t: t.hash == torrent1_hash, client.torrents_info())
filter(lambda t: t.hash == torrent_hash, client.torrents_info())
)[0]
except:
if attempt >= _check_limit - 1:
Expand Down
Binary file not shown.
1 change: 1 addition & 0 deletions tests/root_folder.torrent
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
d10:created by18:qBittorrent v4.3.013:creation datei1618171953e4:infod5:filesld6:lengthi15e4:pathl8:file.txteee4:name11:root_folder12:piece lengthi16384e6:pieces20:�m�rR���-v?J���|7:privatei1eee
90 changes: 78 additions & 12 deletions tests/test_torrents.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from qbittorrentapi.exceptions import Forbidden403Error
from qbittorrentapi.exceptions import Conflict409Error
from qbittorrentapi.exceptions import InvalidRequest400Error
from qbittorrentapi.exceptions import MissingRequiredParameters400Error
from qbittorrentapi.exceptions import TorrentFileError
from qbittorrentapi.exceptions import TorrentFileNotFoundError
from qbittorrentapi.exceptions import TorrentFilePermissionError
Expand All @@ -31,7 +32,10 @@

from tests.conftest import (
check,
new_torrent_standalone,
retry,
root_folder_torrent_hash,
root_folder_torrent_file,
torrent1_filename,
torrent2_filename,
torrent1_hash,
Expand Down Expand Up @@ -208,20 +212,78 @@ def fake_open(*arg, **kwargs):
client.torrents_add(torrent_files="/etc/hosts")


def test_add_options(api_version, new_torrent):
check(lambda: new_torrent.category, "test_category")
@pytest.mark.parametrize("keep_root_folder", (True, False, None))
@pytest.mark.parametrize(
"content_layout", (None, "Original", "Subfolder", "NoSubfolder")
)
def test_add_options(client, api_version, keep_root_folder, content_layout):
client.torrents_delete(torrent_hashes=root_folder_torrent_hash, delete_files=True)
if is_version_less_than("2.3.0", api_version, lteq=True):
client.torrents_create_tags("option-tag")
torrent = next(
new_torrent_standalone(
torrent_hash=root_folder_torrent_hash,
client=client,
torrent_files=root_folder_torrent_file,
save_path=path.expanduser("~/test_download/"),
category="test_category",
is_paused=True,
upload_limit=1024,
download_limit=2048,
is_sequential_download=True,
is_first_last_piece_priority=True,
is_root_folder=keep_root_folder,
rename="this is a new name for the torrent",
use_auto_torrent_management=False,
tags="option-tag",
content_layout=content_layout,
ratio_limit=2,
seeding_time_limit=120,
)
)
check(lambda: torrent.category, "test_category")
check(
lambda: new_torrent.state,
lambda: torrent.state,
("pausedDL", "checkingResumeData"),
reverse=True,
any=True,
)
check(lambda: new_torrent.save_path, path.expanduser("~/test_download/"))
check(lambda: new_torrent.up_limit, 1024)
check(lambda: new_torrent.dl_limit, 2048)
check(lambda: new_torrent.seq_dl, True)
if is_version_less_than("2.0.0", api_version, lteq=False):
check(lambda: new_torrent.f_l_piece_prio, True)
check(lambda: torrent.save_path, path.expanduser("~/test_download/"))
check(lambda: torrent.up_limit, 1024)
check(lambda: torrent.dl_limit, 2048)
check(lambda: torrent.seq_dl, True)
if is_version_less_than("2.0.1", api_version, lteq=True):
check(lambda: torrent.f_l_piece_prio, True)
if content_layout is None:
check(
lambda: torrent.files[0]["name"].startswith("root_folder"),
keep_root_folder in {True, None},
)
check(lambda: torrent.name, "this is a new name for the torrent")
check(lambda: torrent.auto_tmm, False)
if is_version_less_than("2.6.2", api_version, lteq=True):
check(lambda: torrent.tags, "option-tag")

if is_version_less_than("2.7", api_version, lteq=True):
# after web api v2.7...root dir is driven by content_layout
if content_layout is None:
should_root_dir_exists = keep_root_folder in {None, True}
else:
should_root_dir_exists = content_layout in {"Original", "Subfolder"}
else:
# before web api v2.7...it is driven by is_root_folder
if content_layout is not None and keep_root_folder is None:
should_root_dir_exists = content_layout in {"Original", "Subfolder"}
else:
should_root_dir_exists = keep_root_folder in {None, True}
check(
lambda: any(f["name"].startswith("root_folder") for f in torrent.files),
should_root_dir_exists,
)

if is_version_less_than("2.8.1", api_version, lteq=True):
check(lambda: torrent.ratio_limit, 2)
check(lambda: torrent.seeding_time_limit, 120)


def test_properties(client, orig_torrent):
Expand Down Expand Up @@ -353,24 +415,28 @@ def test_rename_file(
torrent_hash=new_torrent.hash, file_id=0, new_file_name=new_name
)
else:
# pre-v4.3.3 rename_file signature
getattr(client, client_func)(
torrent_hash=new_torrent.hash, file_id=0, new_file_name=new_name
)
check(lambda: new_torrent.files[0].name.replace("+", " "), new_name)

# test invalid file ID is rejected
with pytest.raises(Conflict409Error):
getattr(client, client_func)(
torrent_hash=new_torrent.hash, file_id=10, new_file_name=new_name
)

if is_version_less_than("v4.3.2", app_version, lteq=False):
# post-v4.3.3 rename_file signature
getattr(client, client_func)(
torrent_hash=new_torrent.hash,
old_path=new_torrent.files[0].name,
new_path=new_name + "_new",
)
check(lambda: new_torrent.files[0].name.replace("+", " "), new_name + "_new")
# test invalid old_path is rejected
with pytest.raises(Conflict409Error):
getattr(client, client_func)(
torrent_hash=new_torrent.hash, old_path="asdf", new_path="xcvb"
)


@pytest.mark.parametrize("new_name", ("asdf zxcv", "asdf_zxcv"))
Expand Down

0 comments on commit 679e130

Please sign in to comment.