|
15 | 15 | import requests
|
16 | 16 | from requests.packages import urllib3
|
17 | 17 | import six
|
| 18 | +import struct |
18 | 19 |
|
19 | 20 | from . import fake_api
|
20 | 21 |
|
@@ -467,56 +468,121 @@ def test_early_stream_response(self):
|
467 | 468 |
|
468 | 469 |
|
469 | 470 | class TCPSocketStreamTest(unittest.TestCase):
|
470 |
| - text_data = b''' |
| 471 | + stdout_data = b''' |
471 | 472 | Now, those children out there, they're jumping through the
|
472 | 473 | flames in the hope that the god of the fire will make them fruitful.
|
473 | 474 | Really, you can't blame them. After all, what girl would not prefer the
|
474 | 475 | child of a god to that of some acne-scarred artisan?
|
475 | 476 | '''
|
| 477 | + stderr_data = b''' |
| 478 | + And what of the true God? To whose glory churches and monasteries have been |
| 479 | + built on these islands for generations past? Now shall what of Him? |
| 480 | + ''' |
476 | 481 |
|
477 | 482 | def setUp(self):
|
478 |
| - |
479 | 483 | self.server = six.moves.socketserver.ThreadingTCPServer(
|
480 |
| - ('', 0), self.get_handler_class() |
481 |
| - ) |
| 484 | + ('', 0), self.get_handler_class()) |
482 | 485 | self.thread = threading.Thread(target=self.server.serve_forever)
|
483 | 486 | self.thread.setDaemon(True)
|
484 | 487 | self.thread.start()
|
485 | 488 | self.address = 'http://{}:{}'.format(
|
486 |
| - socket.gethostname(), self.server.server_address[1] |
487 |
| - ) |
| 489 | + socket.gethostname(), self.server.server_address[1]) |
488 | 490 |
|
489 | 491 | def tearDown(self):
|
490 | 492 | self.server.shutdown()
|
491 | 493 | self.server.server_close()
|
492 | 494 | self.thread.join()
|
493 | 495 |
|
494 | 496 | def get_handler_class(self):
|
495 |
| - text_data = self.text_data |
| 497 | + stdout_data = self.stdout_data |
| 498 | + stderr_data = self.stderr_data |
496 | 499 |
|
497 | 500 | class Handler(six.moves.BaseHTTPServer.BaseHTTPRequestHandler, object):
|
498 | 501 | def do_POST(self):
|
| 502 | + resp_data = self.get_resp_data() |
499 | 503 | self.send_response(101)
|
500 | 504 | self.send_header(
|
501 |
| - 'Content-Type', 'application/vnd.docker.raw-stream' |
502 |
| - ) |
| 505 | + 'Content-Type', 'application/vnd.docker.raw-stream') |
503 | 506 | self.send_header('Connection', 'Upgrade')
|
504 | 507 | self.send_header('Upgrade', 'tcp')
|
505 | 508 | self.end_headers()
|
506 | 509 | self.wfile.flush()
|
507 | 510 | time.sleep(0.2)
|
508 |
| - self.wfile.write(text_data) |
| 511 | + self.wfile.write(resp_data) |
509 | 512 | self.wfile.flush()
|
510 | 513 |
|
| 514 | + def get_resp_data(self): |
| 515 | + path = self.path.split('/')[-1] |
| 516 | + if path == 'tty': |
| 517 | + return stdout_data + stderr_data |
| 518 | + elif path == 'no-tty': |
| 519 | + data = b'' |
| 520 | + data += self.frame_header(1, stdout_data) |
| 521 | + data += stdout_data |
| 522 | + data += self.frame_header(2, stderr_data) |
| 523 | + data += stderr_data |
| 524 | + return data |
| 525 | + else: |
| 526 | + raise Exception('Unknown path {0}'.format(path)) |
| 527 | + |
| 528 | + @staticmethod |
| 529 | + def frame_header(stream, data): |
| 530 | + return struct.pack('>BxxxL', stream, len(data)) |
| 531 | + |
511 | 532 | return Handler
|
512 | 533 |
|
513 |
| - def test_read_from_socket(self): |
| 534 | + def request(self, stream=None, tty=None, demux=None): |
| 535 | + assert stream is not None and tty is not None and demux is not None |
514 | 536 | with APIClient(base_url=self.address) as client:
|
515 |
| - resp = client._post(client._url('/dummy'), stream=True) |
516 |
| - data = client._read_from_socket(resp, stream=True, tty=True) |
517 |
| - results = b''.join(data) |
518 |
| - |
519 |
| - assert results == self.text_data |
| 537 | + if tty: |
| 538 | + url = client._url('/tty') |
| 539 | + else: |
| 540 | + url = client._url('/no-tty') |
| 541 | + resp = client._post(url, stream=True) |
| 542 | + return client._read_from_socket( |
| 543 | + resp, stream=stream, tty=tty, demux=demux) |
| 544 | + |
| 545 | + def test_read_from_socket_1(self): |
| 546 | + res = self.request(stream=True, tty=True, demux=False) |
| 547 | + assert next(res) == self.stdout_data + self.stderr_data |
| 548 | + with self.assertRaises(StopIteration): |
| 549 | + next(res) |
| 550 | + |
| 551 | + def test_read_from_socket_2(self): |
| 552 | + res = self.request(stream=True, tty=True, demux=True) |
| 553 | + assert next(res) == (self.stdout_data + self.stderr_data, None) |
| 554 | + with self.assertRaises(StopIteration): |
| 555 | + next(res) |
| 556 | + |
| 557 | + def test_read_from_socket_3(self): |
| 558 | + res = self.request(stream=True, tty=False, demux=False) |
| 559 | + assert next(res) == self.stdout_data |
| 560 | + assert next(res) == self.stderr_data |
| 561 | + with self.assertRaises(StopIteration): |
| 562 | + next(res) |
| 563 | + |
| 564 | + def test_read_from_socket_4(self): |
| 565 | + res = self.request(stream=True, tty=False, demux=True) |
| 566 | + assert (self.stdout_data, None) == next(res) |
| 567 | + assert (None, self.stderr_data) == next(res) |
| 568 | + with self.assertRaises(StopIteration): |
| 569 | + next(res) |
| 570 | + |
| 571 | + def test_read_from_socket_5(self): |
| 572 | + res = self.request(stream=False, tty=True, demux=False) |
| 573 | + assert res == self.stdout_data + self.stderr_data |
| 574 | + |
| 575 | + def test_read_from_socket_6(self): |
| 576 | + res = self.request(stream=False, tty=True, demux=True) |
| 577 | + assert res == (self.stdout_data + self.stderr_data, b'') |
| 578 | + |
| 579 | + def test_read_from_socket_7(self): |
| 580 | + res = self.request(stream=False, tty=False, demux=False) |
| 581 | + res == self.stdout_data + self.stderr_data |
| 582 | + |
| 583 | + def test_read_from_socket_8(self): |
| 584 | + res = self.request(stream=False, tty=False, demux=True) |
| 585 | + assert res == (self.stdout_data, self.stderr_data) |
520 | 586 |
|
521 | 587 |
|
522 | 588 | class UserAgentTest(unittest.TestCase):
|
|
0 commit comments