Requests are responded to in the order in which they were received See https://www.rfc-editor.org/rfc/rfc7230#section-6.3.2
(self)
| 250 | |
| 251 | |
| 252 | def check_pipelining(self): |
| 253 | """ |
| 254 | Requests are responded to in the order in which they were received |
| 255 | See https://www.rfc-editor.org/rfc/rfc7230#section-6.3.2 |
| 256 | """ |
| 257 | self.log.info("Check pipelining") |
| 258 | tip_height = self.node.getblockcount() |
| 259 | conn = BitcoinHTTPConnection(self.node) |
| 260 | conn.set_timeout(5) |
| 261 | |
| 262 | # Send two requests in a row. |
| 263 | # The first request will block the second indefinitely |
| 264 | conn.post_raw('/', f'{{"method": "waitforblockheight", "params": [{tip_height + 1}]}}') |
| 265 | conn.post_raw('/', '{"method": "getblockcount"}') |
| 266 | |
| 267 | try: |
| 268 | # The server should not respond to the second request until the first |
| 269 | # request has been handled. Since the server will not respond at all |
| 270 | # to the first request until we generate a block we expect a socket timeout. |
| 271 | conn.recv_raw() |
| 272 | assert False |
| 273 | except TimeoutError: |
| 274 | pass |
| 275 | |
| 276 | # Use a separate http connection to generate a block |
| 277 | self.generate(self.node, 1, sync_fun=self.no_op) |
| 278 | |
| 279 | # Wait for two responses to be received |
| 280 | res = b"" |
| 281 | while res.count(b"result") != 2: |
| 282 | res += conn.recv_raw() |
| 283 | |
| 284 | # waitforblockheight was responded to first, and then getblockcount |
| 285 | # which includes the block added after the request was made |
| 286 | chunks = res.split(b'"result":') |
| 287 | assert chunks[1].startswith(b'{"hash":') |
| 288 | assert chunks[2].startswith(bytes(f'{tip_height + 1}', 'utf8')) |
| 289 | |
| 290 | |
| 291 | def check_chunked_transfer(self): |
no test coverage detected