Mercurial > hg
comparison tests/testlib/badserverext.py @ 48613:b060e305d79f
test-http-bad-server: factor code dealing with "read" in the new object
This will make sure both `read` and `readline` do the same processing and make
it simpler to update that processing in the future.
Differential Revision: https://phab.mercurial-scm.org/D12044
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Fri, 21 Jan 2022 03:05:43 +0100 |
parents | 11e5cb170d36 |
children | 3efc8644dd00 |
comparison
equal
deleted
inserted
replaced
48612:11e5cb170d36 | 48613:b060e305d79f |
---|---|
144 object.__getattribute__(obj, '_cond_close')() | 144 object.__getattribute__(obj, '_cond_close')() |
145 raise Exception('connection closed after sending N bytes') | 145 raise Exception('connection closed after sending N bytes') |
146 | 146 |
147 return result | 147 return result |
148 | 148 |
149 def forward_read(self, obj, method, size=-1): | |
150 """call an underlying read function until condition are met | |
151 | |
152 When the condition are met the socket is closed | |
153 """ | |
154 remaining = self.remaining_recv_bytes | |
155 | |
156 orig = object.__getattribute__(obj, '_orig') | |
157 bmethod = method.encode('ascii') | |
158 func = getattr(orig, method) | |
159 | |
160 # No read limit. Call original function. | |
161 if not remaining: | |
162 result = func(size) | |
163 obj._writelog( | |
164 b'%s(%d) -> (%d) %s' % (bmethod, size, len(result), result) | |
165 ) | |
166 return result | |
167 | |
168 origsize = size | |
169 | |
170 if size < 0: | |
171 size = remaining | |
172 else: | |
173 size = min(remaining, size) | |
174 | |
175 result = func(size) | |
176 remaining -= len(result) | |
177 | |
178 obj._writelog( | |
179 b'%s(%d from %d) -> (%d) %s' | |
180 % (bmethod, size, origsize, len(result), result) | |
181 ) | |
182 | |
183 self.remaining_recv_bytes = remaining | |
184 | |
185 if remaining <= 0: | |
186 obj._writelog(b'read limit reached; closing socket') | |
187 obj._cond_close() | |
188 | |
189 # This is the easiest way to abort the current request. | |
190 raise Exception('connection closed after receiving N bytes') | |
191 | |
192 return result | |
193 | |
149 | 194 |
150 # We can't adjust __class__ on a socket instance. So we define a proxy type. | 195 # We can't adjust __class__ on a socket instance. So we define a proxy type. |
151 class socketproxy(object): | 196 class socketproxy(object): |
152 __slots__ = ('_orig', '_logfp', '_cond') | 197 __slots__ = ('_orig', '_logfp', '_cond') |
153 | 198 |
238 self.close() | 283 self.close() |
239 else: | 284 else: |
240 self._sock.shutdown(socket.SHUT_RDWR) | 285 self._sock.shutdown(socket.SHUT_RDWR) |
241 | 286 |
242 def read(self, size=-1): | 287 def read(self, size=-1): |
243 remaining = object.__getattribute__(self, '_cond').remaining_recv_bytes | 288 cond = object.__getattribute__(self, '_cond') |
244 | 289 return cond.forward_read(self, 'read', size) |
245 # No read limit. Call original function. | |
246 if not remaining: | |
247 result = object.__getattribute__(self, '_orig').read(size) | |
248 self._writelog( | |
249 b'read(%d) -> (%d) (%s) %s' % (size, len(result), result) | |
250 ) | |
251 return result | |
252 | |
253 origsize = size | |
254 | |
255 if size < 0: | |
256 size = remaining | |
257 else: | |
258 size = min(remaining, size) | |
259 | |
260 result = object.__getattribute__(self, '_orig').read(size) | |
261 remaining -= len(result) | |
262 | |
263 self._writelog( | |
264 b'read(%d from %d) -> (%d) %s' | |
265 % (size, origsize, len(result), result) | |
266 ) | |
267 | |
268 object.__getattribute__(self, '_cond').remaining_recv_bytes = remaining | |
269 | |
270 if remaining <= 0: | |
271 self._writelog(b'read limit reached; closing socket') | |
272 self._close() | |
273 | |
274 # This is the easiest way to abort the current request. | |
275 raise Exception('connection closed after receiving N bytes') | |
276 | |
277 return result | |
278 | 290 |
279 def readline(self, size=-1): | 291 def readline(self, size=-1): |
280 remaining = object.__getattribute__(self, '_cond').remaining_recv_bytes | 292 cond = object.__getattribute__(self, '_cond') |
281 | 293 return cond.forward_read(self, 'readline', size) |
282 # No read limit. Call original function. | |
283 if not remaining: | |
284 result = object.__getattribute__(self, '_orig').readline(size) | |
285 self._writelog( | |
286 b'readline(%d) -> (%d) %s' % (size, len(result), result) | |
287 ) | |
288 return result | |
289 | |
290 origsize = size | |
291 | |
292 if size < 0: | |
293 size = remaining | |
294 else: | |
295 size = min(remaining, size) | |
296 | |
297 result = object.__getattribute__(self, '_orig').readline(size) | |
298 remaining -= len(result) | |
299 | |
300 self._writelog( | |
301 b'readline(%d from %d) -> (%d) %s' | |
302 % (size, origsize, len(result), result) | |
303 ) | |
304 | |
305 object.__getattribute__(self, '_cond').remaining_recv_bytes = remaining | |
306 | |
307 if remaining <= 0: | |
308 self._writelog(b'read limit reached; closing socket') | |
309 self._close() | |
310 | |
311 # This is the easiest way to abort the current request. | |
312 raise Exception('connection closed after receiving N bytes') | |
313 | |
314 return result | |
315 | 294 |
316 def write(self, data): | 295 def write(self, data): |
317 cond = object.__getattribute__(self, '_cond') | 296 cond = object.__getattribute__(self, '_cond') |
318 return cond.forward_write(self, 'write', data) | 297 return cond.forward_write(self, 'write', data) |
319 | 298 |