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