Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: third_party/google-endpoints/apitools/base/py/transfer_test.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 #
2 # Copyright 2015 Google Inc.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 """Tests for transfer.py."""
17 import string
18
19 import mock
20 import six
21 from six.moves import http_client
22 import unittest2
23
24 from apitools.base.py import base_api
25 from apitools.base.py import http_wrapper
26 from apitools.base.py import transfer
27
28
29 class TransferTest(unittest2.TestCase):
30
31 def assertRangeAndContentRangeCompatible(self, request, response):
32 request_prefix = 'bytes='
33 self.assertIn('range', request.headers)
34 self.assertTrue(request.headers['range'].startswith(request_prefix))
35 request_range = request.headers['range'][len(request_prefix):]
36
37 response_prefix = 'bytes '
38 self.assertIn('content-range', response.info)
39 response_header = response.info['content-range']
40 self.assertTrue(response_header.startswith(response_prefix))
41 response_range = (
42 response_header[len(response_prefix):].partition('/')[0])
43
44 msg = ('Request range ({0}) not a prefix of '
45 'response_range ({1})').format(
46 request_range, response_range)
47 self.assertTrue(response_range.startswith(request_range), msg=msg)
48
49 def testComputeEndByte(self):
50 total_size = 100
51 chunksize = 10
52 download = transfer.Download.FromStream(
53 six.StringIO(), chunksize=chunksize, total_size=total_size)
54 self.assertEqual(chunksize - 1,
55 download._Download__ComputeEndByte(0, end=50))
56
57 def testComputeEndByteReturnNone(self):
58 download = transfer.Download.FromStream(six.StringIO())
59 self.assertIsNone(
60 download._Download__ComputeEndByte(0, use_chunks=False))
61
62 def testComputeEndByteNoChunks(self):
63 total_size = 100
64 download = transfer.Download.FromStream(
65 six.StringIO(), chunksize=10, total_size=total_size)
66 for end in (None, 1000):
67 self.assertEqual(
68 total_size - 1,
69 download._Download__ComputeEndByte(0, end=end,
70 use_chunks=False),
71 msg='Failed on end={0}'.format(end))
72
73 def testComputeEndByteNoTotal(self):
74 download = transfer.Download.FromStream(six.StringIO())
75 default_chunksize = download.chunksize
76 for chunksize in (100, default_chunksize):
77 download.chunksize = chunksize
78 for start in (0, 10):
79 self.assertEqual(
80 download.chunksize + start - 1,
81 download._Download__ComputeEndByte(start),
82 msg='Failed on start={0}, chunksize={1}'.format(
83 start, chunksize))
84
85 def testComputeEndByteSmallTotal(self):
86 total_size = 100
87 download = transfer.Download.FromStream(six.StringIO(),
88 total_size=total_size)
89 for start in (0, 10):
90 self.assertEqual(total_size - 1,
91 download._Download__ComputeEndByte(start),
92 msg='Failed on start={0}'.format(start))
93
94 def testGetRange(self):
95 for (start_byte, end_byte) in [(0, 25), (5, 15), (0, 0), (25, 25)]:
96 bytes_http = object()
97 http = object()
98 download_stream = six.StringIO()
99 download = transfer.Download.FromStream(download_stream,
100 total_size=26,
101 auto_transfer=False)
102 download.bytes_http = bytes_http
103 base_url = 'https://part.one/'
104 with mock.patch.object(http_wrapper, 'MakeRequest',
105 autospec=True) as make_request:
106 make_request.return_value = http_wrapper.Response(
107 info={
108 'content-range': 'bytes %d-%d/26' %
109 (start_byte, end_byte),
110 'status': http_client.OK,
111 },
112 content=string.ascii_lowercase[start_byte:end_byte+1],
113 request_url=base_url,
114 )
115 request = http_wrapper.Request(url='https://part.one/')
116 download.InitializeDownload(request, http=http)
117 download.GetRange(start_byte, end_byte)
118 self.assertEqual(1, make_request.call_count)
119 received_request = make_request.call_args[0][1]
120 self.assertEqual(base_url, received_request.url)
121 self.assertRangeAndContentRangeCompatible(
122 received_request, make_request.return_value)
123
124 def testNonChunkedDownload(self):
125 bytes_http = object()
126 http = object()
127 download_stream = six.StringIO()
128 download = transfer.Download.FromStream(download_stream, total_size=52)
129 download.bytes_http = bytes_http
130 base_url = 'https://part.one/'
131
132 with mock.patch.object(http_wrapper, 'MakeRequest',
133 autospec=True) as make_request:
134 make_request.return_value = http_wrapper.Response(
135 info={
136 'content-range': 'bytes 0-51/52',
137 'status': http_client.OK,
138 },
139 content=string.ascii_lowercase * 2,
140 request_url=base_url,
141 )
142 request = http_wrapper.Request(url='https://part.one/')
143 download.InitializeDownload(request, http=http)
144 self.assertEqual(1, make_request.call_count)
145 received_request = make_request.call_args[0][1]
146 self.assertEqual(base_url, received_request.url)
147 self.assertRangeAndContentRangeCompatible(
148 received_request, make_request.return_value)
149 download_stream.seek(0)
150 self.assertEqual(string.ascii_lowercase * 2,
151 download_stream.getvalue())
152
153 def testChunkedDownload(self):
154 bytes_http = object()
155 http = object()
156 download_stream = six.StringIO()
157 download = transfer.Download.FromStream(
158 download_stream, chunksize=26, total_size=52)
159 download.bytes_http = bytes_http
160
161 # Setting autospec on a mock with an iterable side_effect is
162 # currently broken (http://bugs.python.org/issue17826), so
163 # instead we write a little function.
164 def _ReturnBytes(unused_http, http_request,
165 *unused_args, **unused_kwds):
166 url = http_request.url
167 if url == 'https://part.one/':
168 return http_wrapper.Response(
169 info={
170 'content-location': 'https://part.two/',
171 'content-range': 'bytes 0-25/52',
172 'status': http_client.PARTIAL_CONTENT,
173 },
174 content=string.ascii_lowercase,
175 request_url='https://part.one/',
176 )
177 elif url == 'https://part.two/':
178 return http_wrapper.Response(
179 info={
180 'content-range': 'bytes 26-51/52',
181 'status': http_client.OK,
182 },
183 content=string.ascii_uppercase,
184 request_url='https://part.two/',
185 )
186 else:
187 self.fail('Unknown URL requested: %s' % url)
188
189 with mock.patch.object(http_wrapper, 'MakeRequest',
190 autospec=True) as make_request:
191 make_request.side_effect = _ReturnBytes
192 request = http_wrapper.Request(url='https://part.one/')
193 download.InitializeDownload(request, http=http)
194 self.assertEqual(2, make_request.call_count)
195 for call in make_request.call_args_list:
196 self.assertRangeAndContentRangeCompatible(
197 call[0][1], _ReturnBytes(*call[0]))
198 download_stream.seek(0)
199 self.assertEqual(string.ascii_lowercase + string.ascii_uppercase,
200 download_stream.getvalue())
201
202 def testFromEncoding(self):
203 # Test a specific corner case in multipart encoding.
204
205 # Python's mime module by default encodes lines that start with
206 # "From " as ">From ", which we need to make sure we don't run afoul
207 # of when sending content that isn't intended to be so encoded. This
208 # test calls out that we get this right. We test for both the
209 # multipart and non-multipart case.
210 multipart_body = '{"body_field_one": 7}'
211 upload_contents = 'line one\nFrom \nline two'
212 upload_config = base_api.ApiUploadInfo(
213 accept=['*/*'],
214 max_size=None,
215 resumable_multipart=True,
216 resumable_path=u'/resumable/upload',
217 simple_multipart=True,
218 simple_path=u'/upload',
219 )
220 url_builder = base_api._UrlBuilder('http://www.uploads.com')
221
222 # Test multipart: having a body argument in http_request forces
223 # multipart here.
224 upload = transfer.Upload.FromStream(
225 six.StringIO(upload_contents),
226 'text/plain',
227 total_size=len(upload_contents))
228 http_request = http_wrapper.Request(
229 'http://www.uploads.com',
230 headers={'content-type': 'text/plain'},
231 body=multipart_body)
232 upload.ConfigureRequest(upload_config, http_request, url_builder)
233 self.assertEqual(url_builder.query_params['uploadType'], 'multipart')
234 rewritten_upload_contents = '\n'.join(
235 http_request.body.split('--')[2].splitlines()[1:])
236 self.assertTrue(rewritten_upload_contents.endswith(upload_contents))
237
238 # Test non-multipart (aka media): no body argument means this is
239 # sent as media.
240 upload = transfer.Upload.FromStream(
241 six.StringIO(upload_contents),
242 'text/plain',
243 total_size=len(upload_contents))
244 http_request = http_wrapper.Request(
245 'http://www.uploads.com',
246 headers={'content-type': 'text/plain'})
247 upload.ConfigureRequest(upload_config, http_request, url_builder)
248 self.assertEqual(url_builder.query_params['uploadType'], 'media')
249 rewritten_upload_contents = http_request.body
250 self.assertTrue(rewritten_upload_contents.endswith(upload_contents))
OLDNEW
« no previous file with comments | « third_party/google-endpoints/apitools/base/py/transfer.py ('k') | third_party/google-endpoints/apitools/base/py/util.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698