|
1 | 1 | from __future__ import print_function |
2 | 2 |
|
| 3 | +import asyncio |
3 | 4 | import functools |
4 | 5 | import os |
5 | 6 | import platform |
|
35 | 36 | except ImportError: |
36 | 37 | from io import StringIO |
37 | 38 |
|
38 | | - |
39 | 39 | if hunter.Tracer.__module__ == 'hunter.tracer': |
40 | 40 |
|
41 | 41 | class EvilFrame(object): |
@@ -85,7 +85,6 @@ def __exit__(self, exc_type, exc_val, exc_tb): |
85 | 85 | else: |
86 | 86 | from eviltracer import EvilTracer |
87 | 87 |
|
88 | | - |
89 | 88 | trace = EvilTracer |
90 | 89 |
|
91 | 90 | pytest_plugins = ('pytester',) |
@@ -599,6 +598,89 @@ def foo(): |
599 | 598 | assert 'tracer.stop()' not in call |
600 | 599 |
|
601 | 600 |
|
| 601 | +def test_wraps_generator(LineMatcher): |
| 602 | + calls = [] |
| 603 | + |
| 604 | + @hunter.wrap(action=lambda event: calls.append('%6r calls=%r depth=%r %s' % (event.kind, event.calls, event.depth, event.fullsource))) |
| 605 | + def foo(): |
| 606 | + yield 1 |
| 607 | + |
| 608 | + assert list(foo()) == [1] |
| 609 | + lm = LineMatcher(calls) |
| 610 | + for line in calls: |
| 611 | + print(repr(line)) |
| 612 | + lm.fnmatch_lines( |
| 613 | + [ |
| 614 | + "'call' calls=0 depth=0 @hunter.wrap*", |
| 615 | + "'line' calls=1 depth=1 yield 1\n", |
| 616 | + "'return' calls=1 depth=0 yield 1\n", |
| 617 | + ] |
| 618 | + ) |
| 619 | + for call in calls: |
| 620 | + assert 'tracer.stop()' not in call |
| 621 | + |
| 622 | + |
| 623 | +def test_wraps_async_generator(LineMatcher): |
| 624 | + calls = [] |
| 625 | + |
| 626 | + @hunter.wrap( |
| 627 | + action=lambda event: calls.append( |
| 628 | + '%s %6r calls=%r depth=%r %s' % (event.module, event.kind, event.calls, event.depth, event.fullsource) |
| 629 | + ) |
| 630 | + ) |
| 631 | + async def foo(): |
| 632 | + yield 1 |
| 633 | + await asyncio.sleep(0.01) |
| 634 | + |
| 635 | + async def runner(): |
| 636 | + result = [] |
| 637 | + async for item in foo(): |
| 638 | + result.append(item) |
| 639 | + return result |
| 640 | + |
| 641 | + assert asyncio.run(runner()) == [1] |
| 642 | + lm = LineMatcher(calls) |
| 643 | + for line in calls: |
| 644 | + print(repr(line)) |
| 645 | + lm.fnmatch_lines( |
| 646 | + [ |
| 647 | + "test_tracer 'call' calls=* depth=0 @hunter.wrap*", |
| 648 | + "test_tracer 'line' calls=* depth=1 yield 1\n", |
| 649 | + "test_tracer 'return' calls=* depth=0 yield 1\n", |
| 650 | + ] |
| 651 | + ) |
| 652 | + for call in calls: |
| 653 | + assert 'tracer.stop()' not in call |
| 654 | + |
| 655 | + |
| 656 | +def test_wraps_coroutine(LineMatcher): |
| 657 | + calls = [] |
| 658 | + |
| 659 | + @hunter.wrap( |
| 660 | + action=lambda event: calls.append( |
| 661 | + '%s %6r calls=%r depth=%r %s' % (event.module, event.kind, event.calls, event.depth, event.fullsource) |
| 662 | + ) |
| 663 | + ) |
| 664 | + async def foo(): |
| 665 | + await asyncio.sleep(0.01) |
| 666 | + print(1) |
| 667 | + return 1 |
| 668 | + |
| 669 | + assert asyncio.run(foo()) == 1 |
| 670 | + lm = LineMatcher(calls) |
| 671 | + for line in calls: |
| 672 | + print(repr(line)) |
| 673 | + lm.fnmatch_lines( |
| 674 | + [ |
| 675 | + "test_tracer 'call' calls=0 depth=0 @hunter.wrap*", |
| 676 | + "test_tracer 'line' calls=1 depth=1 await asyncio.sleep(0.01)\n", |
| 677 | + "test_tracer 'return' calls=* depth=0 await asyncio.sleep(0.01)\n", |
| 678 | + ] |
| 679 | + ) |
| 680 | + for call in calls: |
| 681 | + assert 'tracer.stop()' not in call |
| 682 | + |
| 683 | + |
602 | 684 | def test_wraps_local(LineMatcher): |
603 | 685 | calls = [] |
604 | 686 |
|
@@ -630,6 +712,111 @@ def foo(): |
630 | 712 | assert 'tracer.stop()' not in call |
631 | 713 |
|
632 | 714 |
|
| 715 | +def test_wraps_generator_local(LineMatcher): |
| 716 | + calls = [] |
| 717 | + |
| 718 | + def bar(): |
| 719 | + for i in range(2): |
| 720 | + return 'A' |
| 721 | + |
| 722 | + @hunter.wrap( |
| 723 | + local=True, action=lambda event: calls.append('%6r calls=%r depth=%r %s' % (event.kind, event.calls, event.depth, event.fullsource)) |
| 724 | + ) |
| 725 | + def foo(): |
| 726 | + bar() |
| 727 | + yield 1 |
| 728 | + |
| 729 | + assert list(foo()) == [1] |
| 730 | + lm = LineMatcher(calls) |
| 731 | + for line in calls: |
| 732 | + print(repr(line)) |
| 733 | + lm.fnmatch_lines( |
| 734 | + [ |
| 735 | + "'call' calls=0 depth=0 @hunter.wrap*", |
| 736 | + "'line' calls=* depth=1 yield 1\n", |
| 737 | + "'return' calls=* depth=0 yield 1\n", |
| 738 | + ] |
| 739 | + ) |
| 740 | + for call in calls: |
| 741 | + assert 'for i in range(2)' not in call |
| 742 | + assert 'tracer.stop()' not in call |
| 743 | + |
| 744 | + |
| 745 | +def test_wraps_async_generator_local(LineMatcher): |
| 746 | + calls = [] |
| 747 | + |
| 748 | + def bar(): |
| 749 | + for i in range(2): |
| 750 | + return 'A' |
| 751 | + |
| 752 | + @hunter.wrap( |
| 753 | + local=True, |
| 754 | + action=lambda event: calls.append( |
| 755 | + '%s %6r calls=%r depth=%r %s' % (event.module, event.kind, event.calls, event.depth, event.fullsource) |
| 756 | + ), |
| 757 | + ) |
| 758 | + async def foo(): |
| 759 | + bar() |
| 760 | + yield 1 |
| 761 | + await asyncio.sleep(0.01) |
| 762 | + |
| 763 | + async def runner(): |
| 764 | + result = [] |
| 765 | + async for item in foo(): |
| 766 | + result.append(item) |
| 767 | + return result |
| 768 | + |
| 769 | + assert asyncio.run(runner()) == [1] |
| 770 | + lm = LineMatcher(calls) |
| 771 | + for line in calls: |
| 772 | + print(repr(line)) |
| 773 | + lm.fnmatch_lines( |
| 774 | + [ |
| 775 | + "test_tracer 'call' calls=* depth=0 @hunter.wrap*", |
| 776 | + "test_tracer 'line' calls=* depth=1 yield 1\n", |
| 777 | + "test_tracer 'return' calls=* depth=0 yield 1\n", |
| 778 | + ] |
| 779 | + ) |
| 780 | + for call in calls: |
| 781 | + assert 'for i in range(2)' not in call |
| 782 | + assert 'tracer.stop()' not in call |
| 783 | + |
| 784 | + |
| 785 | +def test_wraps_coroutine_local(LineMatcher): |
| 786 | + calls = [] |
| 787 | + |
| 788 | + def bar(): |
| 789 | + for i in range(2): |
| 790 | + return 'A' |
| 791 | + |
| 792 | + @hunter.wrap( |
| 793 | + local=True, |
| 794 | + action=lambda event: calls.append( |
| 795 | + '%s %6r calls=%r depth=%r %s' % (event.module, event.kind, event.calls, event.depth, event.fullsource) |
| 796 | + ), |
| 797 | + ) |
| 798 | + async def foo(): |
| 799 | + bar() |
| 800 | + await asyncio.sleep(0.01) |
| 801 | + print(1) |
| 802 | + return 1 |
| 803 | + |
| 804 | + assert asyncio.run(foo()) == 1 |
| 805 | + lm = LineMatcher(calls) |
| 806 | + for line in calls: |
| 807 | + print(repr(line)) |
| 808 | + lm.fnmatch_lines( |
| 809 | + [ |
| 810 | + "test_tracer 'call' calls=0 depth=0 @hunter.wrap*", |
| 811 | + "test_tracer 'line' calls=* depth=1 await asyncio.sleep(0.01)\n", |
| 812 | + "test_tracer 'return' calls=* depth=0 await asyncio.sleep(0.01)\n", |
| 813 | + ] |
| 814 | + ) |
| 815 | + for call in calls: |
| 816 | + assert 'for i in range(2)' not in call |
| 817 | + assert 'tracer.stop()' not in call |
| 818 | + |
| 819 | + |
633 | 820 | @pytest.mark.skipif('os.environ.get("SETUPPY_CFLAGS") == "-DCYTHON_TRACE=1"') |
634 | 821 | def test_depth(): |
635 | 822 | calls = [] |
|
0 commit comments