Skip to content

Commit 5abb0ec

Browse files
AndreMirasinclement
authored andcommitted
Unit tests Recipe.download_file() partly (#1952)
Follow up of #1946. Increases coverage by testing part of `Recipe.download_file()` handling https schema. Next up would be to handle more schemas in the tests. Also addressed @opacam comments from previous pull requests.
1 parent 588d65d commit 5abb0ec

File tree

2 files changed

+63
-10
lines changed

2 files changed

+63
-10
lines changed

pythonforandroid/toolchain.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -743,12 +743,11 @@ def _read_configuration():
743743
def recipes(self, args):
744744
"""
745745
Prints recipes basic info, e.g.
746-
```
747-
python3 3.7.1
748-
depends: ['hostpython3', 'sqlite3', 'openssl', 'libffi']
749-
conflicts: ['python2']
750-
optional depends: ['sqlite3', 'libffi', 'openssl']
751-
```
746+
.. code-block:: bash
747+
python3 3.7.1
748+
depends: ['hostpython3', 'sqlite3', 'openssl', 'libffi']
749+
conflicts: ['python2']
750+
optional depends: ['sqlite3', 'libffi', 'openssl']
752751
"""
753752
ctx = self.ctx
754753
if args.compact:

tests/test_recipe.py

+58-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
import pytest
23
import types
34
import unittest
45
import warnings
@@ -20,6 +21,10 @@ def patch_logger_debug():
2021
return patch_logger('debug')
2122

2223

24+
def patch_urlretrieve():
25+
return mock.patch('pythonforandroid.recipe.urlretrieve')
26+
27+
2328
class DummyRecipe(Recipe):
2429
pass
2530

@@ -94,21 +99,34 @@ def test_download_if_necessary(self):
9499
recipe.download_if_necessary()
95100
assert m_download.call_args_list == []
96101

97-
def test_download(self):
102+
def test_download_url_not_set(self):
98103
"""
99-
Verifies the actual download gets triggered when the URL is set.
104+
Verifies that no download happens when URL is not set.
100105
"""
101-
# test with no URL set
102106
recipe = DummyRecipe()
103107
with patch_logger_info() as m_info:
104108
recipe.download()
105109
assert m_info.call_args_list == [
106110
mock.call('Skipping test_recipe download as no URL is set')]
107-
# when the URL is set `Recipe.download_file()` should be called
111+
112+
@staticmethod
113+
def get_dummy_python_recipe_for_download_tests():
114+
"""
115+
Helper method for creating a test recipe used in download tests.
116+
"""
117+
recipe = DummyRecipe()
108118
filename = 'Python-3.7.4.tgz'
109119
url = 'https://www.python.org/ftp/python/3.7.4/{}'.format(filename)
110120
recipe._url = url
111121
recipe.ctx = Context()
122+
return recipe, filename
123+
124+
def test_download_url_is_set(self):
125+
"""
126+
Verifies the actual download gets triggered when the URL is set.
127+
"""
128+
recipe, filename = self.get_dummy_python_recipe_for_download_tests()
129+
url = recipe.url
112130
with (
113131
patch_logger_debug()) as m_debug, (
114132
mock.patch.object(Recipe, 'download_file')) as m_download_file, (
@@ -122,3 +140,39 @@ def test_download(self):
122140
'Downloading test_recipe from '
123141
'https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tgz')]
124142
assert m_touch.call_count == 1
143+
144+
def test_download_file_scheme_https(self):
145+
"""
146+
Verifies `urlretrieve()` is being called on https downloads.
147+
"""
148+
recipe, filename = self.get_dummy_python_recipe_for_download_tests()
149+
url = recipe.url
150+
with (
151+
patch_urlretrieve()) as m_urlretrieve, (
152+
tempfile.TemporaryDirectory()) as temp_dir:
153+
recipe.ctx.setup_dirs(temp_dir)
154+
assert recipe.download_file(url, filename) == filename
155+
assert m_urlretrieve.call_args_list == [
156+
mock.call(url, filename, mock.ANY)
157+
]
158+
159+
def test_download_file_scheme_https_oserror(self):
160+
"""
161+
Checks `urlretrieve()` is being retried on `OSError`.
162+
After a number of retries the exception is re-reaised.
163+
"""
164+
recipe, filename = self.get_dummy_python_recipe_for_download_tests()
165+
url = recipe.url
166+
with (
167+
patch_urlretrieve()) as m_urlretrieve, (
168+
mock.patch('pythonforandroid.recipe.time.sleep')) as m_sleep, (
169+
pytest.raises(OSError)), (
170+
tempfile.TemporaryDirectory()) as temp_dir:
171+
recipe.ctx.setup_dirs(temp_dir)
172+
m_urlretrieve.side_effect = OSError
173+
assert recipe.download_file(url, filename) == filename
174+
retry = 5
175+
expected_call_args_list = [mock.call(url, filename, mock.ANY)] * retry
176+
assert m_urlretrieve.call_args_list == expected_call_args_list
177+
expected_call_args_list = [mock.call(1)] * (retry - 1)
178+
assert m_sleep.call_args_list == expected_call_args_list

0 commit comments

Comments
 (0)