1
1
import os
2
+ import pytest
2
3
import types
3
4
import unittest
4
5
import warnings
@@ -20,6 +21,10 @@ def patch_logger_debug():
20
21
return patch_logger ('debug' )
21
22
22
23
24
+ def patch_urlretrieve ():
25
+ return mock .patch ('pythonforandroid.recipe.urlretrieve' )
26
+
27
+
23
28
class DummyRecipe (Recipe ):
24
29
pass
25
30
@@ -94,21 +99,34 @@ def test_download_if_necessary(self):
94
99
recipe .download_if_necessary ()
95
100
assert m_download .call_args_list == []
96
101
97
- def test_download (self ):
102
+ def test_download_url_not_set (self ):
98
103
"""
99
- Verifies the actual download gets triggered when the URL is set.
104
+ Verifies that no download happens when URL is not set.
100
105
"""
101
- # test with no URL set
102
106
recipe = DummyRecipe ()
103
107
with patch_logger_info () as m_info :
104
108
recipe .download ()
105
109
assert m_info .call_args_list == [
106
110
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 ()
108
118
filename = 'Python-3.7.4.tgz'
109
119
url = 'https://www.python.org/ftp/python/3.7.4/{}' .format (filename )
110
120
recipe ._url = url
111
121
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
112
130
with (
113
131
patch_logger_debug ()) as m_debug , (
114
132
mock .patch .object (Recipe , 'download_file' )) as m_download_file , (
@@ -122,3 +140,39 @@ def test_download(self):
122
140
'Downloading test_recipe from '
123
141
'https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tgz' )]
124
142
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