| | 464 | def test_decodingBadTrailerFirstByte(self): |
| | 465 | """ |
| | 466 | L{_ChunkedTransferDecoder.dataReceived} raises RuntimeError when |
| | 467 | it expects the first byte of the trailer but gets something else. |
| | 468 | """ |
| | 469 | L = [] |
| | 470 | p = http._ChunkedTransferDecoder(L.append, None) |
| | 471 | p.dataReceived('3\r\nabc\r\n4\r\n1234') |
| | 472 | self.assertRaises(RuntimeError, lambda: p.dataReceived('5')) |
| | 473 | |
| | 474 | |
| | 475 | def test_decodingButBadSecondByte(self): |
| | 476 | """ |
| | 477 | L{_ChunkedTransferDecoder.dataReceived} raises RuntimeError when |
| | 478 | it expects the second byte of the trailer but gets something else. |
| | 479 | """ |
| | 480 | L = [] |
| | 481 | p = http._ChunkedTransferDecoder(L.append, None) |
| | 482 | p.dataReceived('3\r\nabc\r\n4\r\n1234') |
| | 483 | p.dataReceived('\r') |
| | 484 | self.assertRaises(RuntimeError, lambda: p.dataReceived('x')) |
| | 485 | |
| | 486 | |
| | 487 | def test_chunkLengthNegative(self): |
| | 488 | """ |
| | 489 | L{_ChunkedTransferDecoder.dataReceived} raises RuntimeError |
| | 490 | when the chunk length string is negative. |
| | 491 | """ |
| | 492 | L = [] |
| | 493 | p = http._ChunkedTransferDecoder(L.append, None) |
| | 494 | self.assertRaises(RuntimeError, lambda: p.dataReceived('-3\r\nsomething')) |
| | 495 | |
| | 496 | |
| | 497 | def test_chunkLengthNegativeZero(self): |
| | 498 | """ |
| | 499 | L{_ChunkedTransferDecoder.dataReceived} does not raise RuntimeError |
| | 500 | when the chunk length is "-0". |
| | 501 | |
| | 502 | At this time, stricter RFC2616 validation would bring no benefits. |
| | 503 | """ |
| | 504 | L = [] |
| | 505 | finished = [] |
| | 506 | p = http._ChunkedTransferDecoder(L.append, finished.append) |
| | 507 | p.dataReceived('1\r\nX\r\n-0\r\n\r\n') |
| | 508 | self.assertEqual(L, ['X']) |
| | 509 | self.assertEqual(finished, ['']) |
| | 510 | |
| | 511 | |
| | 512 | def test_tooLongChunkLength(self): |
| | 513 | """ |
| | 514 | L{_ChunkedTransferDecoder.dataReceived} raises RuntimeError |
| | 515 | when the chunk length string is too long. |
| | 516 | """ |
| | 517 | L = [] |
| | 518 | p = http._ChunkedTransferDecoder(L.append, None) |
| | 519 | max = p._maximumChunkLengthBytes |
| | 520 | |
| | 521 | self.assertRaises(RuntimeError, lambda: p.dataReceived( |
| | 522 | ('9' * (max+1)) + '\r\n' + ('s' * (max+1)))) |
| | 523 | |
| | 524 | |
| | 525 | def test_tooLongChunkLengthWithExtension(self): |
| | 526 | """ |
| | 527 | L{_ChunkedTransferDecoder.dataReceived} immediately raises |
| | 528 | RuntimeError when the chunk length string is too long, even when |
| | 529 | it contains the beginning of a chunk extension. |
| | 530 | """ |
| | 531 | L = [] |
| | 532 | p = http._ChunkedTransferDecoder(L.append, None) |
| | 533 | max = p._maximumChunkLengthBytes |
| | 534 | |
| | 535 | self.assertRaises(RuntimeError, lambda: p.dataReceived( |
| | 536 | (('9' * (max+1)) + ';'))) |
| | 537 | |
| | 538 | |
| | 539 | def test_tooLongChunkLengthWithExtensionGoodMath(self): |
| | 540 | """ |
| | 541 | L{_ChunkedTransferDecoder.dataReceived} doesn't include |
| | 542 | the length of the semicolon when determining the length |
| | 543 | of the chunked length string. |
| | 544 | """ |
| | 545 | L = [] |
| | 546 | p = http._ChunkedTransferDecoder(L.append, None) |
| | 547 | max = p._maximumChunkLengthBytes |
| | 548 | |
| | 549 | p.dataReceived((('9' * (max)) + ';')) |
| | 550 | |
| | 551 | |
| | 552 | def test_chunkTooLongSeparate(self): |
| | 553 | """ |
| | 554 | L{_ChunkedTransferDecoder.dataReceived} raises RuntimeError |
| | 555 | when the chunk length string is too long, even when the last byte |
| | 556 | is sent separately. |
| | 557 | """ |
| | 558 | L = [] |
| | 559 | p = http._ChunkedTransferDecoder(L.append, None) |
| | 560 | max = p._maximumChunkLengthBytes |
| | 561 | |
| | 562 | p.dataReceived(('9' * max)) |
| | 563 | |
| | 564 | self.assertRaises(RuntimeError, lambda: p.dataReceived('9')) |
| | 565 | |
| | 566 | |
| | 567 | def test_chunkInvalidHex(self): |
| | 568 | """ |
| | 569 | L{_ChunkedTransferDecoder.dataReceived} raises RuntimeError |
| | 570 | when the chunk is invalid hex. |
| | 571 | """ |
| | 572 | L = [] |
| | 573 | p = http._ChunkedTransferDecoder(L.append, None) |
| | 574 | self.assertRaises(RuntimeError, lambda: p.dataReceived( |
| | 575 | '9G\r\nsomething')) |
| | 576 | |
| | 577 | |
| | 578 | def test_chunkInvalidGarbage(self): |
| | 579 | """ |
| | 580 | L{_ChunkedTransferDecoder.dataReceived} raises RuntimeError |
| | 581 | when the chunk is garbage. |
| | 582 | """ |
| | 583 | L = [] |
| | 584 | p = http._ChunkedTransferDecoder(L.append, None) |
| | 585 | self.assertRaises(RuntimeError, lambda: p.dataReceived( |
| | 586 | '#$\][,.\'!@#*&\r\nsomething')) |
| | 587 | |
| | 588 | |
| | 589 | def test_shortStrayCRInExtension(self): |
| | 590 | """ |
| | 591 | L{_ChunkedTransferDecoder.dataReceived} ignores CR in chunk |
| | 592 | extensions. |
| | 593 | """ |
| | 594 | L = [] |
| | 595 | finished = [] |
| | 596 | p = http._ChunkedTransferDecoder(L.append, finished.append) |
| | 597 | for s in '3\r\nabc\r\n5; extension=some\rthing\r\n12345\r\n0\r\n\r\n': |
| | 598 | p.dataReceived(s) |
| | 599 | self.assertEqual(L, ['a', 'b', 'c', '1', '2', '3', '4', '5']) |
| | 600 | self.assertEqual(finished, ['']) |
| | 601 | |
| | 602 | |
| | 639 | def test_extensions(self): |
| | 640 | """ |
| | 641 | L{_ChunkedTransferDecoder.dataReceived} disregards chunk-extension |
| | 642 | fields, even when they are long. |
| | 643 | """ |
| | 644 | L = [] |
| | 645 | p = http._ChunkedTransferDecoder(L.append, None) |
| | 646 | p.dataReceived('3; x-foo-long-long-long=bar-pretty-long\r\nabc\r\n') |
| | 647 | self.assertEqual(L, ['abc']) |
| | 648 | |
| | 649 | |
| | 650 | def test_extensionsShortDelivery(self): |
| | 651 | """ |
| | 652 | L{_ChunkedTransferDecoder.dataReceived} disregards chunk-extension |
| | 653 | fields, even when delivered in multiple calls. |
| | 654 | """ |
| | 655 | L = [] |
| | 656 | p = http._ChunkedTransferDecoder(L.append, None) |
| | 657 | for s in '3; x-foo-long-long-long=bar-pretty-long\r\nabc\r\n': |
| | 658 | p.dataReceived(s) |
| | 659 | self.assertEqual(L, ['a', 'b', 'c']) |
| | 660 | |
| | 661 | |
| | 662 | def test_extensionsShortDeliveryVariant(self): |
| | 663 | """ |
| | 664 | L{_ChunkedTransferDecoder.dataReceived} disregards chunk-extension |
| | 665 | fields, even when delivered in multiple calls, with the first call including |
| | 666 | the semicolon and space. |
| | 667 | """ |
| | 668 | L = [] |
| | 669 | p = http._ChunkedTransferDecoder(L.append, None) |
| | 670 | p.dataReceived('3; ') |
| | 671 | for s in 'x-foo-long-long-long=bar-pretty-long\r\nabc\r\n': |
| | 672 | p.dataReceived(s) |
| | 673 | self.assertEqual(L, ['a', 'b', 'c']) |
| | 674 | |
| | 675 | |
| | 676 | def test_extensionsShortDeliveryTwoBytes(self): |
| | 677 | """ |
| | 678 | L{_ChunkedTransferDecoder.dataReceived} disregards chunk-extension |
| | 679 | fields, even when the chunk requires two bytes of chunk-length bytes to |
| | 680 | represent the length. |
| | 681 | """ |
| | 682 | L = [] |
| | 683 | p = http._ChunkedTransferDecoder(L.append, None) |
| | 684 | # 0x14 == 20 |
| | 685 | for s in '14; x-foo-long-long-long=bar-pretty-long\r\n'+('a'*20)+'\r\n': |
| | 686 | p.dataReceived(s) |
| | 687 | self.assertEqual(L, ['a']*20) |
| | 688 | |
| | 689 | |