bgneal@1225
|
1 import unittest
|
bgneal@1225
|
2 from urlparse import urlparse, ParseResult
|
bgneal@1225
|
3
|
bgneal@1225
|
4 from mock import call, patch, mock_open, Mock
|
bgneal@1225
|
5
|
bgneal@1225
|
6 from core.download import download_file
|
bgneal@1225
|
7
|
bgneal@1225
|
8
|
bgneal@1225
|
9 class DownloadFileTestCase(unittest.TestCase):
|
bgneal@1225
|
10 """Unit tests for the download_file function."""
|
bgneal@1225
|
11
|
bgneal@1225
|
12 @patch('core.download.requests')
|
bgneal@1225
|
13 def test_get_throws_exception(self, requests_mock):
|
bgneal@1225
|
14 requests_mock.get.side_effect = RuntimeError('ope')
|
bgneal@1225
|
15 r = None
|
bgneal@1225
|
16 try:
|
bgneal@1225
|
17 r = download_file('url', path='path', timeout=5.0)
|
bgneal@1225
|
18 except RuntimeError:
|
bgneal@1225
|
19 pass
|
bgneal@1225
|
20 except Exception as e:
|
bgneal@1225
|
21 self.fail('Unexpected exception {}'.format(e))
|
bgneal@1225
|
22
|
bgneal@1225
|
23 self.assertIsNone(r)
|
bgneal@1225
|
24 self.assertEqual(requests_mock.get.mock_calls, [
|
bgneal@1225
|
25 call('url', stream=True, timeout=5.0),
|
bgneal@1225
|
26 ])
|
bgneal@1225
|
27
|
bgneal@1225
|
28 @patch('core.download.requests')
|
bgneal@1225
|
29 def test_get_returns_non_success(self, requests_mock):
|
bgneal@1225
|
30 response_mock = Mock()
|
bgneal@1225
|
31 response_mock.status_code = 404
|
bgneal@1225
|
32 requests_mock.get.return_value = response_mock
|
bgneal@1225
|
33 r = download_file('url', path='path', timeout=5.0)
|
bgneal@1225
|
34
|
bgneal@1225
|
35 self.assertIsNone(r)
|
bgneal@1225
|
36 self.assertEqual(requests_mock.get.mock_calls, [
|
bgneal@1225
|
37 call('url', stream=True, timeout=5.0),
|
bgneal@1225
|
38 ])
|
bgneal@1225
|
39
|
bgneal@1225
|
40 @patch('core.download.os.stat')
|
bgneal@1225
|
41 @patch('core.download.shutil.copyfileobj')
|
bgneal@1225
|
42 @patch('core.download.requests')
|
bgneal@1225
|
43 def test_happy_path_with_path_argument(self, requests_mock, copy_mock,
|
bgneal@1225
|
44 stat_mock):
|
bgneal@1225
|
45 response_mock = Mock()
|
bgneal@1225
|
46 response_mock.status_code = 200
|
bgneal@1225
|
47 requests_mock.get.return_value = response_mock
|
bgneal@1225
|
48
|
bgneal@1225
|
49 stat_mock.st_size = 512
|
bgneal@1225
|
50
|
bgneal@1225
|
51 open_mock = mock_open()
|
bgneal@1225
|
52 with patch('__builtin__.open', open_mock):
|
bgneal@1225
|
53 r = download_file('url', path='path', timeout=5.0)
|
bgneal@1225
|
54
|
bgneal@1225
|
55 self.assertEqual(r, 'path')
|
bgneal@1225
|
56 self.assertEqual(requests_mock.get.mock_calls, [
|
bgneal@1225
|
57 call('url', stream=True, timeout=5.0),
|
bgneal@1225
|
58 ])
|
bgneal@1225
|
59 self.assertTrue(response_mock.raw.decode_content)
|
bgneal@1225
|
60 self.assertEqual(copy_mock.mock_calls, [
|
bgneal@1225
|
61 call(response_mock.raw, open_mock.return_value),
|
bgneal@1225
|
62 ])
|
bgneal@1225
|
63
|
bgneal@1225
|
64 @patch('core.download.os.remove')
|
bgneal@1225
|
65 @patch('core.download.shutil.copyfileobj')
|
bgneal@1225
|
66 @patch('core.download.requests')
|
bgneal@1225
|
67 def test_copyfileobj_raises(self, requests_mock, copy_mock, remove_mock):
|
bgneal@1225
|
68 response_mock = Mock()
|
bgneal@1225
|
69 response_mock.status_code = 200
|
bgneal@1225
|
70 requests_mock.get.return_value = response_mock
|
bgneal@1225
|
71
|
bgneal@1225
|
72 copy_mock.side_effect = IOError
|
bgneal@1225
|
73
|
bgneal@1225
|
74 open_mock = mock_open()
|
bgneal@1225
|
75 with patch('__builtin__.open', open_mock):
|
bgneal@1225
|
76 try:
|
bgneal@1225
|
77 download_file('url', path='path', timeout=5.0)
|
bgneal@1225
|
78 except IOError:
|
bgneal@1225
|
79 pass
|
bgneal@1225
|
80 else:
|
bgneal@1225
|
81 self.fail('Should have thrown')
|
bgneal@1225
|
82
|
bgneal@1225
|
83 self.assertEqual(requests_mock.get.mock_calls, [
|
bgneal@1225
|
84 call('url', stream=True, timeout=5.0),
|
bgneal@1225
|
85 ])
|
bgneal@1225
|
86 self.assertTrue(response_mock.raw.decode_content)
|
bgneal@1225
|
87 self.assertEqual(copy_mock.mock_calls, [
|
bgneal@1225
|
88 call(response_mock.raw, open_mock.return_value),
|
bgneal@1225
|
89 ])
|
bgneal@1225
|
90 self.assertEqual(remove_mock.mock_calls, [
|
bgneal@1225
|
91 call('path'),
|
bgneal@1225
|
92 ])
|
bgneal@1225
|
93
|
bgneal@1225
|
94
|
bgneal@1225
|
95 @patch('core.download.os')
|
bgneal@1225
|
96 @patch('core.download.tempfile')
|
bgneal@1225
|
97 @patch('core.download.mimetypes')
|
bgneal@1225
|
98 @patch('core.download.os.remove')
|
bgneal@1225
|
99 @patch('core.download.shutil.copyfileobj')
|
bgneal@1225
|
100 @patch('core.download.requests')
|
bgneal@1225
|
101 def test_happy_path_with_suffix(self, requests_mock, copy_mock, remove_mock,
|
bgneal@1225
|
102 mime_mock, tempfile_mock, os_mock):
|
bgneal@1225
|
103 response_mock = Mock()
|
bgneal@1225
|
104 response_mock.status_code = 200
|
bgneal@1225
|
105 requests_mock.get.return_value = response_mock
|
bgneal@1225
|
106
|
bgneal@1225
|
107 response_mock.headers.get.return_value = 'image/jpeg'
|
bgneal@1225
|
108 mime_mock.guess_extension.return_value = '.jpe'
|
bgneal@1225
|
109 fd_mock = Mock()
|
bgneal@1225
|
110 tempfile_mock.mkstemp.return_value = (fd_mock, 'temp-path')
|
bgneal@1225
|
111
|
bgneal@1225
|
112 open_mock = mock_open()
|
bgneal@1225
|
113 with patch('__builtin__.open', open_mock):
|
bgneal@1225
|
114 download_file('url', timeout=5.0)
|
bgneal@1225
|
115
|
bgneal@1225
|
116 self.assertEqual(requests_mock.get.mock_calls, [
|
bgneal@1225
|
117 call('url', stream=True, timeout=5.0),
|
bgneal@1225
|
118 call().headers.get('content-type'),
|
bgneal@1225
|
119 ])
|
bgneal@1225
|
120 self.assertEqual(response_mock.headers.get.mock_calls, [
|
bgneal@1225
|
121 call('content-type'),
|
bgneal@1225
|
122 ])
|
bgneal@1225
|
123 self.assertEqual(mime_mock.guess_extension.mock_calls, [
|
bgneal@1225
|
124 call('image/jpeg'),
|
bgneal@1225
|
125 ])
|
bgneal@1225
|
126 self.assertEqual(tempfile_mock.mkstemp.mock_calls, [
|
bgneal@1225
|
127 call(suffix='.jpg'),
|
bgneal@1225
|
128 ])
|
bgneal@1225
|
129 self.assertEqual(os_mock.close.mock_calls, [
|
bgneal@1225
|
130 call(fd_mock),
|
bgneal@1225
|
131 ])
|
bgneal@1225
|
132 self.assertTrue(response_mock.raw.decode_content)
|
bgneal@1225
|
133 self.assertEqual(copy_mock.mock_calls, [
|
bgneal@1225
|
134 call(response_mock.raw, open_mock.return_value),
|
bgneal@1225
|
135 ])
|
bgneal@1225
|
136
|
bgneal@1225
|
137
|
bgneal@1225
|
138 @patch('core.download.urlparse')
|
bgneal@1225
|
139 @patch('core.download.os')
|
bgneal@1225
|
140 @patch('core.download.tempfile')
|
bgneal@1225
|
141 @patch('core.download.mimetypes')
|
bgneal@1225
|
142 @patch('core.download.os.remove')
|
bgneal@1225
|
143 @patch('core.download.shutil.copyfileobj')
|
bgneal@1225
|
144 @patch('core.download.requests')
|
bgneal@1225
|
145 def test_happy_path_with_no_suffix(self, requests_mock, copy_mock,
|
bgneal@1225
|
146 remove_mock, mime_mock, tempfile_mock,
|
bgneal@1225
|
147 os_mock, urlparse_mock):
|
bgneal@1225
|
148 response_mock = Mock()
|
bgneal@1225
|
149 response_mock.status_code = 200
|
bgneal@1225
|
150 requests_mock.get.return_value = response_mock
|
bgneal@1225
|
151
|
bgneal@1225
|
152 response_mock.headers.get.return_value = None
|
bgneal@1225
|
153 urlparse_mock.return_value = ParseResult(
|
bgneal@1225
|
154 scheme='https', netloc='www.example.com', path='/something.txt',
|
bgneal@1225
|
155 params='', query='', fragment='')
|
bgneal@1225
|
156 os_mock.path.splitext.return_value = ('/something', '.txt')
|
bgneal@1225
|
157 fd_mock = Mock()
|
bgneal@1225
|
158 tempfile_mock.mkstemp.return_value = (fd_mock, 'temp-path')
|
bgneal@1225
|
159
|
bgneal@1225
|
160 open_mock = mock_open()
|
bgneal@1225
|
161 with patch('__builtin__.open', open_mock):
|
bgneal@1225
|
162 download_file('url', timeout=5.0)
|
bgneal@1225
|
163
|
bgneal@1225
|
164 self.assertEqual(requests_mock.get.mock_calls, [
|
bgneal@1225
|
165 call('url', stream=True, timeout=5.0),
|
bgneal@1225
|
166 call().headers.get('content-type'),
|
bgneal@1225
|
167 ])
|
bgneal@1225
|
168 self.assertEqual(response_mock.headers.get.mock_calls, [
|
bgneal@1225
|
169 call('content-type'),
|
bgneal@1225
|
170 ])
|
bgneal@1225
|
171 self.assertEqual(urlparse_mock.mock_calls, [
|
bgneal@1225
|
172 call('url'),
|
bgneal@1225
|
173 ])
|
bgneal@1225
|
174 self.assertEqual(mime_mock.guess_extension.mock_calls, [])
|
bgneal@1225
|
175 self.assertEqual(os_mock.path.splitext.mock_calls, [
|
bgneal@1225
|
176 call('/something.txt'),
|
bgneal@1225
|
177 ])
|
bgneal@1225
|
178 self.assertEqual(tempfile_mock.mkstemp.mock_calls, [
|
bgneal@1225
|
179 call(suffix='.txt'),
|
bgneal@1225
|
180 ])
|
bgneal@1225
|
181 self.assertEqual(os_mock.close.mock_calls, [
|
bgneal@1225
|
182 call(fd_mock),
|
bgneal@1225
|
183 ])
|
bgneal@1225
|
184 self.assertTrue(response_mock.raw.decode_content)
|
bgneal@1225
|
185 self.assertEqual(copy_mock.mock_calls, [
|
bgneal@1225
|
186 call(response_mock.raw, open_mock.return_value),
|
bgneal@1225
|
187 ])
|