From 5e2a9468c15a7a13ec2fe084fdd3c892f807d649 Mon Sep 17 00:00:00 2001 From: Evgeny Ezhov Date: Tue, 17 Dec 2019 12:20:29 +0300 Subject: [PATCH] Increase test coverage --- tests/__init__.py | 0 tests/base_client_it.py | 69 ++++++++++++++++++++++++ tests/test_client_it.py | 84 ++++++++--------------------- tests/test_client_resource_it.py | 75 ++++++++++++++++++++++++++ tests/test_client_unit.py | 7 ++- tests/test_connection.py | 91 ++++++++++++++++++++++++++++++++ tests/test_exceptions.py | 50 ++++++++++++++++++ webdav3/client.py | 17 +++--- webdav3/connection.py | 1 + webdav3/exceptions.py | 2 +- 10 files changed, 327 insertions(+), 69 deletions(-) create mode 100644 tests/__init__.py create mode 100644 tests/base_client_it.py create mode 100644 tests/test_client_resource_it.py create mode 100644 tests/test_connection.py create mode 100644 tests/test_exceptions.py diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/base_client_it.py b/tests/base_client_it.py new file mode 100644 index 0000000..b8bce2f --- /dev/null +++ b/tests/base_client_it.py @@ -0,0 +1,69 @@ +import os +import shutil +import unittest +from os import path + +from webdav3.client import Client + + +class BaseClientTestCase(unittest.TestCase): + remote_path_file = 'test_dir/test.txt' + remote_path_file2 = 'test_dir2/test.txt' + remote_inner_path_file = 'test_dir/inner/test.txt' + remote_path_dir = 'test_dir' + remote_path_dir2 = 'test_dir2' + remote_inner_path_dir = 'test_dir/inner' + local_base_dir = 'tests/' + local_file = 'test.txt' + local_file_path = local_base_dir + 'test.txt' + local_path_dir = local_base_dir + 'res/test_dir' + + options = { + 'webdav_hostname': 'http://localhost:8585', + 'webdav_login': 'alice', + 'webdav_password': 'secret1234' + } + + # options = { + # 'webdav_hostname': 'https://webdav.yandex.ru', + # 'webdav_login': 'webdavclient.test2', + # 'webdav_password': 'Qwerty123!' + # } + + def setUp(self): + self.client = Client(self.options) + if path.exists(path=self.local_path_dir): + shutil.rmtree(path=self.local_path_dir) + + def tearDown(self): + if path.exists(path=self.local_path_dir): + shutil.rmtree(path=self.local_path_dir) + if self.client.check(remote_path=self.remote_path_dir): + self.client.clean(remote_path=self.remote_path_dir) + if self.client.check(remote_path=self.remote_path_dir2): + self.client.clean(remote_path=self.remote_path_dir2) + + def _prepare_for_downloading(self, inner_dir=False): + if not self.client.check(remote_path=self.remote_path_dir): + self.client.mkdir(remote_path=self.remote_path_dir) + if not self.client.check(remote_path=self.remote_path_file): + self.client.upload_file(remote_path=self.remote_path_file, local_path=self.local_file_path) + if not path.exists(self.local_path_dir): + os.makedirs(self.local_path_dir) + if inner_dir: + if not self.client.check(remote_path=self.remote_inner_path_dir): + self.client.mkdir(remote_path=self.remote_inner_path_dir) + if not self.client.check(remote_path=self.remote_inner_path_file): + self.client.upload_file(remote_path=self.remote_inner_path_file, local_path=self.local_file_path) + + def _prepare_for_uploading(self): + if not self.client.check(remote_path=self.remote_path_dir): + self.client.mkdir(remote_path=self.remote_path_dir) + if not path.exists(path=self.local_path_dir): + os.makedirs(self.local_path_dir) + if not path.exists(path=self.local_path_dir + os.sep + self.local_file): + shutil.copy(src=self.local_file_path, dst=self.local_path_dir + os.sep + self.local_file) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_client_it.py b/tests/test_client_it.py index 2d45316..900df58 100644 --- a/tests/test_client_it.py +++ b/tests/test_client_it.py @@ -1,51 +1,14 @@ import os.path -import shutil import unittest from io import BytesIO, StringIO from os import path from time import sleep -from unittest import TestCase -from webdav3.client import Client -from webdav3.exceptions import MethodNotSupported +from tests.base_client_it import BaseClientTestCase +from webdav3.exceptions import MethodNotSupported, OptionNotValid, RemoteResourceNotFound -class ClientTestCase(TestCase): - remote_path_file = 'test_dir/test.txt' - remote_path_file2 = 'test_dir2/test.txt' - remote_inner_path_file = 'test_dir/inner/test.txt' - remote_path_dir = 'test_dir' - remote_path_dir2 = 'test_dir2' - remote_inner_path_dir = 'test_dir/inner' - local_base_dir = 'tests/' - local_file = 'test.txt' - local_file_path = local_base_dir + 'test.txt' - local_path_dir = local_base_dir + 'res/test_dir' - - options = { - 'webdav_hostname': 'http://localhost:8585', - 'webdav_login': 'alice', - 'webdav_password': 'secret1234' - } - - # options = { - # 'webdav_hostname': 'https://webdav.yandex.ru', - # 'webdav_login': 'webdavclient.test2', - # 'webdav_password': 'Qwerty123!' - # } - - def setUp(self): - self.client = Client(self.options) - if path.exists(path=self.local_path_dir): - shutil.rmtree(path=self.local_path_dir) - - def tearDown(self): - if path.exists(path=self.local_path_dir): - shutil.rmtree(path=self.local_path_dir) - if self.client.check(remote_path=self.remote_path_dir): - self.client.clean(remote_path=self.remote_path_dir) - if self.client.check(remote_path=self.remote_path_dir2): - self.client.clean(remote_path=self.remote_path_dir2) +class ClientTestCase(BaseClientTestCase): def test_list(self): self._prepare_for_downloading() @@ -69,12 +32,29 @@ class ClientTestCase(TestCase): self.client.mkdir(remote_path=self.remote_path_dir) self.assertTrue(self.client.check(remote_path=self.remote_path_dir), 'Expected the directory is created.') - def test_download_to(self): + def test_download_from(self): self._prepare_for_downloading() buff = BytesIO() self.client.download_from(buff=buff, remote_path=self.remote_path_file) self.assertEqual(buff.getvalue(), b'test content for testing of webdav client') + def test_download_from_dir(self): + self._prepare_for_downloading() + buff = BytesIO() + with self.assertRaises(OptionNotValid): + self.client.download_from(buff=buff, remote_path=self.remote_path_dir) + + def test_download_from_wrong_file(self): + self._prepare_for_downloading() + buff = BytesIO() + with self.assertRaises(RemoteResourceNotFound): + self.client.download_from(buff=buff, remote_path='wrong') + + def test_download_directory_wrong(self): + self._prepare_for_downloading() + with self.assertRaises(RemoteResourceNotFound): + self.client.download_directory(remote_path=self.remote_path_file, local_path=self.local_path_dir) + def test_download(self): self._prepare_for_downloading() self.client.download(local_path=self.local_path_dir, remote_path=self.remote_path_dir) @@ -241,26 +221,8 @@ class ClientTestCase(TestCase): self.assertTrue(self.client.check(self.remote_path_dir), 'Expected the directory is created.') self.assertTrue(self.client.check(self.remote_path_file), 'Expected the file is uploaded.') - def _prepare_for_downloading(self, inner_dir=False): - if not self.client.check(remote_path=self.remote_path_dir): - self.client.mkdir(remote_path=self.remote_path_dir) - if not self.client.check(remote_path=self.remote_path_file): - self.client.upload_file(remote_path=self.remote_path_file, local_path=self.local_file_path) - if not path.exists(self.local_path_dir): - os.makedirs(self.local_path_dir) - if inner_dir: - if not self.client.check(remote_path=self.remote_inner_path_dir): - self.client.mkdir(remote_path=self.remote_inner_path_dir) - if not self.client.check(remote_path=self.remote_inner_path_file): - self.client.upload_file(remote_path=self.remote_inner_path_file, local_path=self.local_file_path) - - def _prepare_for_uploading(self): - if not self.client.check(remote_path=self.remote_path_dir): - self.client.mkdir(remote_path=self.remote_path_dir) - if not path.exists(path=self.local_path_dir): - os.makedirs(self.local_path_dir) - if not path.exists(path=self.local_path_dir + os.sep + self.local_file): - shutil.copy(src=self.local_file_path, dst=self.local_path_dir + os.sep + self.local_file) + def test_valid(self): + self.assertTrue(self.client.valid()) if __name__ == '__main__': diff --git a/tests/test_client_resource_it.py b/tests/test_client_resource_it.py new file mode 100644 index 0000000..4f69022 --- /dev/null +++ b/tests/test_client_resource_it.py @@ -0,0 +1,75 @@ +import unittest + +from tests.base_client_it import BaseClientTestCase +from webdav3.client import Resource +from webdav3.urn import Urn + + +class ResourceTestCase(BaseClientTestCase): + + def test_str(self): + self._prepare_for_downloading() + resource = Resource(self.client, Urn(self.remote_path_file)) + self.assertEqual('resource /test_dir/test.txt', resource.__str__()) + + def test_is_not_dir(self): + self._prepare_for_downloading() + resource = Resource(self.client, Urn(self.remote_path_file)) + self.assertFalse(resource.is_dir()) + + def test_is_dir(self): + self._prepare_for_downloading() + resource = Resource(self.client, Urn(self.remote_path_dir)) + self.assertTrue(resource.is_dir()) + + def test_rename(self): + self._prepare_for_downloading() + resource = Resource(self.client, Urn(self.remote_path_file)) + resource.rename('new_name.text') + self.assertTrue(self.client.check(self.remote_path_dir + '/new_name.text')) + + def test_move(self): + self._prepare_for_downloading() + resource = Resource(self.client, Urn(self.remote_path_file)) + self.client.mkdir(self.remote_path_dir2) + resource.move(self.remote_path_file2) + self.assertFalse(self.client.check(self.remote_path_file)) + self.assertTrue(self.client.check(self.remote_path_file2)) + + def test_copy(self): + self._prepare_for_downloading() + resource = Resource(self.client, Urn(self.remote_path_file)) + self.client.mkdir(self.remote_path_dir2) + resource.copy(self.remote_path_file2) + self.assertTrue(self.client.check(self.remote_path_file)) + self.assertTrue(self.client.check(self.remote_path_file2)) + + def test_info(self): + self._prepare_for_downloading() + resource = Resource(self.client, Urn(self.remote_path_file)) + info = resource.info() + self.assertIsNotNone(info) + self.assertGreater(len(info), 0) + + def test_info_params(self): + self._prepare_for_downloading() + resource = Resource(self.client, Urn(self.remote_path_file)) + info = resource.info(['size']) + self.assertIsNotNone(info) + self.assertEqual(1, len(info)) + self.assertTrue('size' in info) + + def test_clean(self): + self._prepare_for_downloading() + resource = Resource(self.client, Urn(self.remote_path_file)) + resource.clean() + self.assertFalse(self.client.check(self.remote_path_file)) + + def test_check(self): + self._prepare_for_downloading() + resource = Resource(self.client, Urn(self.remote_path_file)) + self.assertTrue(resource.check()) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_client_unit.py b/tests/test_client_unit.py index bfa66b9..538c415 100644 --- a/tests/test_client_unit.py +++ b/tests/test_client_unit.py @@ -4,7 +4,7 @@ from unittest import TestCase from lxml.etree import ElementTree, Element -from webdav3.client import WebDavXmlUtils as utils +from webdav3.client import WebDavXmlUtils as utils, listdir class ClientTestCase(TestCase): @@ -156,6 +156,11 @@ class ClientTestCase(TestCase): result = utils.parse_is_dir_response(content.encode('utf-8'), path, hostname) self.assertFalse(result, 'It should be file') + def test_listdir_inner_dir(self): + file_names = listdir('.') + self.assertGreater(len(file_names), 0) + self.assertTrue('webdav3/' in file_names) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_connection.py b/tests/test_connection.py new file mode 100644 index 0000000..dff3772 --- /dev/null +++ b/tests/test_connection.py @@ -0,0 +1,91 @@ +import unittest + +from webdav3.client import get_options +from webdav3.connection import WebDAVSettings, OptionNotValid, ConnectionSettings + + +class ConnectionTestCase(unittest.TestCase): + def test_connection_settings_valid(self): + options = { + 'webdav_hostname': 'http://localhost:8585', + 'webdav_login': 'alice', + 'webdav_password': 'secret1234' + } + webdav_options = get_options(option_type=WebDAVSettings, from_options=options) + settings = WebDAVSettings(webdav_options) + self.assertTrue(settings.is_valid()) + self.assertTrue(settings.valid()) + + def test_connection_settings_no_hostname(self): + options = { + 'webdav_login': 'alice', + 'webdav_password': 'secret1234' + } + webdav_options = get_options(option_type=WebDAVSettings, from_options=options) + settings = WebDAVSettings(webdav_options) + self.assertRaises(OptionNotValid, settings.is_valid) + self.assertFalse(settings.valid()) + + def test_connection_settings_no_login(self): + options = { + 'webdav_hostname': 'http://localhost:8585', + 'webdav_password': 'secret1234' + } + webdav_options = get_options(option_type=WebDAVSettings, from_options=options) + settings = WebDAVSettings(webdav_options) + self.assertRaises(OptionNotValid, settings.is_valid) + self.assertFalse(settings.valid()) + + def test_connection_settings_no_token_and_no_login(self): + options = { + 'webdav_hostname': 'http://localhost:8585' + } + webdav_options = get_options(option_type=WebDAVSettings, from_options=options) + settings = WebDAVSettings(webdav_options) + self.assertRaises(OptionNotValid, settings.is_valid) + self.assertFalse(settings.valid()) + + def test_connection_settings_wrong_cert_path(self): + options = { + 'webdav_hostname': 'http://localhost:8585', + 'webdav_login': 'alice', + 'cert_path': './wrong.file', + 'webdav_password': 'secret1234' + } + webdav_options = get_options(option_type=WebDAVSettings, from_options=options) + settings = WebDAVSettings(webdav_options) + self.assertRaises(OptionNotValid, settings.is_valid) + self.assertFalse(settings.valid()) + + def test_connection_settings_wrong_key_path(self): + options = { + 'webdav_hostname': 'http://localhost:8585', + 'webdav_login': 'alice', + 'key_path': './wrong.file', + 'webdav_password': 'secret1234' + } + webdav_options = get_options(option_type=WebDAVSettings, from_options=options) + settings = WebDAVSettings(webdav_options) + self.assertRaises(OptionNotValid, settings.is_valid) + self.assertFalse(settings.valid()) + + def test_connection_settings_with_key_path_an_no_cert_path(self): + options = { + 'webdav_hostname': 'http://localhost:8585', + 'webdav_login': 'alice', + 'key_path': './publish.sh', + 'webdav_password': 'secret1234' + } + webdav_options = get_options(option_type=WebDAVSettings, from_options=options) + settings = WebDAVSettings(webdav_options) + self.assertRaises(OptionNotValid, settings.is_valid) + self.assertFalse(settings.valid()) + + def test_connection_settings_does_nothing(self): + settings = ConnectionSettings() + settings.is_valid() + self.assertTrue(settings.valid()) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py new file mode 100644 index 0000000..d25d313 --- /dev/null +++ b/tests/test_exceptions.py @@ -0,0 +1,50 @@ +import unittest + +from webdav3.exceptions import OptionNotValid, LocalResourceNotFound, RemoteResourceNotFound, MethodNotSupported, ConnectionException, NoConnection, \ + RemoteParentNotFound, NotConnection, ResponseErrorCode, NotEnoughSpace + + +class ExceptionsTestCase(unittest.TestCase): + def test_option_not_valid(self): + exception = OptionNotValid('Name', 'Value', 'Namespace/') + self.assertEqual("Option (Namespace/Name=Value) have invalid name or value", exception.__str__()) + + def test_local_resource_not_found(self): + exception = LocalResourceNotFound('Path') + self.assertEqual("Local file: Path not found", exception.__str__()) + + def test_remote_resource_not_found(self): + exception = RemoteResourceNotFound('Path') + self.assertEqual("Remote resource: Path not found", exception.__str__()) + + def test_remote_parent_not_found(self): + exception = RemoteParentNotFound('Path') + self.assertEqual("Remote parent for: Path not found", exception.__str__()) + + def test_method_not_supported(self): + exception = MethodNotSupported('HEAD', 'Server') + self.assertEqual("Method 'HEAD' not supported for Server", exception.__str__()) + + def test_connection_exception(self): + exception = ConnectionException(MethodNotSupported('HEAD', 'Server')) + self.assertEqual("Method 'HEAD' not supported for Server", exception.__str__()) + + def test_no_connection(self): + exception = NoConnection('Server') + self.assertEqual("No connection with Server", exception.__str__()) + + def test_not_connection_legacy(self): + exception = NotConnection('Server') + self.assertEqual("No connection with Server", exception.__str__()) + + def test_response_error_code(self): + exception = ResponseErrorCode('http://text/', 502, 'Service Unavailable') + self.assertEqual("Request to http://text/ failed with code 502 and message: Service Unavailable", exception.__str__()) + + def test_not_enough_space(self): + exception = NotEnoughSpace() + self.assertEqual("Not enough space on the server", exception.__str__()) + + +if __name__ == '__main__': + unittest.main() diff --git a/webdav3/client.py b/webdav3/client.py index eab1371..766d0b8 100644 --- a/webdav3/client.py +++ b/webdav3/client.py @@ -277,9 +277,9 @@ class Client(object): :param remote_path: (optional) path to resource on WebDAV server. Defaults is root directory of WebDAV. :return: True if resource is exist or False otherwise """ - if self.webdav.disable_check: return True + urn = Urn(remote_path) try: response = self.execute_request(action='check', path=urn.quote()) @@ -466,7 +466,7 @@ class Client(object): self.mkdir(remote_path) for resource_name in listdir(local_path): - _remote_path = "{parent}{name}".format(parent=urn.path(), name=resource_name) + _remote_path = "{parent}{name}".format(parent=urn.path(), name=resource_name).replace('\\', '') _local_path = os.path.join(local_path, resource_name) self.upload(local_path=_local_path, remote_path=_remote_path, progress=progress) @@ -588,13 +588,16 @@ class Client(object): `modified`: date of resource modification. """ urn = Urn(remote_path) - if not self.check(urn.path()) and not self.check(Urn(remote_path, directory=True).path()): - raise RemoteResourceNotFound(remote_path) + self._check_remote_resource(remote_path, urn) response = self.execute_request(action='info', path=urn.quote()) path = self.get_full_path(urn) return WebDavXmlUtils.parse_info_response(content=response.content, path=path, hostname=self.webdav.hostname) + def _check_remote_resource(self, remote_path, urn): + if not self.check(urn.path()) and not self.check(Urn(remote_path, directory=True).path()): + raise RemoteResourceNotFound(remote_path) + @wrap_connection_error def is_dir(self, remote_path): """Checks is the remote resource directory. @@ -605,8 +608,7 @@ class Client(object): """ urn = Urn(remote_path) parent_urn = Urn(urn.parent()) - if not self.check(urn.path()) and not self.check(Urn(remote_path, directory=True).path()): - raise RemoteResourceNotFound(remote_path) + self._check_remote_resource(remote_path, urn) response = self.execute_request(action='info', path=parent_urn.quote()) path = self.get_full_path(urn) @@ -826,6 +828,9 @@ class Resource(object): class WebDavXmlUtils: + def __init__(self): + pass + @staticmethod def parse_get_list_response(content): """Parses of response content XML from WebDAV server and extract file and directory names. diff --git a/webdav3/connection.py b/webdav3/connection.py index dee4812..ce99211 100644 --- a/webdav3/connection.py +++ b/webdav3/connection.py @@ -68,3 +68,4 @@ class WebDAVSettings(ConnectionSettings): if not self.token and not self.login: raise OptionNotValid(name="login", value=self.login, ns=self.ns) + return True diff --git a/webdav3/exceptions.py b/webdav3/exceptions.py index 718cc7f..7ccf020 100644 --- a/webdav3/exceptions.py +++ b/webdav3/exceptions.py @@ -71,7 +71,7 @@ class NoConnection(WebDavException): self.hostname = hostname def __str__(self): - return "Not connection with {hostname}".format(hostname=self.hostname) + return "No connection with {hostname}".format(hostname=self.hostname) # This exception left only for supporting original library interface.