|
2 | 2 | require 'test/unit'
|
3 | 3 |
|
4 | 4 | class TestAllocation < Test::Unit::TestCase
|
| 5 | + def munge_checks(checks) |
| 6 | + checks |
| 7 | + end |
| 8 | + |
5 | 9 | def check_allocations(checks)
|
6 | 10 | dups = checks.split("\n").reject(&:empty?).tally.select{|_,v| v > 1}
|
7 | 11 | raise "duplicate checks:\n#{dups.keys.join("\n")}" unless dups.empty?
|
8 | 12 |
|
| 13 | + checks = munge_checks(checks) |
| 14 | + |
9 | 15 | assert_separately([], <<~RUBY)
|
10 | 16 | $allocations = [0, 0]
|
11 | 17 | $counts = {}
|
@@ -549,7 +555,8 @@ def self.anon_splat_and_anon_keyword_splat(*, **#{block}); end
|
549 | 555 |
|
550 | 556 | def test_nested_anonymous_splat_and_anonymous_keyword_splat_parameters
|
551 | 557 | check_allocations(<<~RUBY)
|
552 |
| - def self.anon_splat_and_anon_keyword_splat(*, **#{block}); t(*, **) end; def self.t(*, **#{block}); end |
| 558 | + def self.t(*, **#{block}); end |
| 559 | + def self.anon_splat_and_anon_keyword_splat(*, **#{block}); t(*, **) end |
553 | 560 |
|
554 | 561 | check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(1, a: 2#{block})")
|
555 | 562 | check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(1, *empty_array, a: 2#{block})")
|
@@ -639,7 +646,8 @@ def self.argument_forwarding(...); end
|
639 | 646 |
|
640 | 647 | def test_nested_argument_forwarding
|
641 | 648 | check_allocations(<<~RUBY)
|
642 |
| - def self.argument_forwarding(...); t(...) end; def self.t(...) end |
| 649 | + def self.t(...) end |
| 650 | + def self.argument_forwarding(...); t(...) end |
643 | 651 |
|
644 | 652 | check_allocations(0, 0, "argument_forwarding(1, a: 2#{block})")
|
645 | 653 | check_allocations(0, 0, "argument_forwarding(1, *empty_array, a: 2#{block})")
|
@@ -766,4 +774,69 @@ def block
|
766 | 774 | end
|
767 | 775 | end
|
768 | 776 | end
|
| 777 | + |
| 778 | + class ProcCall < MethodCall |
| 779 | + def munge_checks(checks) |
| 780 | + return checks if @no_munge |
| 781 | + sub = rep = nil |
| 782 | + checks.split("\n").map do |line| |
| 783 | + case line |
| 784 | + when "singleton_class.send(:ruby2_keywords, :r2k)" |
| 785 | + "r2k.ruby2_keywords" |
| 786 | + when /\Adef self.([a-z0-9_]+)\((.*)\);(.*)end\z/ |
| 787 | + sub = $1 + '(' |
| 788 | + rep = $1 + '.(' |
| 789 | + "#{$1} = #{$1} = proc{ |#{$2}| #{$3} }" |
| 790 | + when /check_allocations/ |
| 791 | + line.gsub(sub, rep) |
| 792 | + else |
| 793 | + line |
| 794 | + end |
| 795 | + end.join("\n") |
| 796 | + end |
| 797 | + |
| 798 | + # Generic argument forwarding not supported in proc definitions |
| 799 | + undef_method :test_argument_forwarding |
| 800 | + undef_method :test_nested_argument_forwarding |
| 801 | + |
| 802 | + # Proc anonymous arguments cannot be used directly |
| 803 | + undef_method :test_nested_anonymous_splat_and_anonymous_keyword_splat_parameters |
| 804 | + |
| 805 | + def test_no_array_allocation_with_splat_and_nonstatic_keywords |
| 806 | + @no_munge = true |
| 807 | + |
| 808 | + check_allocations(<<~RUBY) |
| 809 | + keyword = keyword = proc{ |a: nil, b: nil #{block}| } |
| 810 | +
|
| 811 | + check_allocations(0, 1, "keyword.(*empty_array, a: empty_array#{block})") # LVAR |
| 812 | + check_allocations(0, 1, "->{keyword.(*empty_array, a: empty_array#{block})}.call") # DVAR |
| 813 | + check_allocations(0, 1, "$x = empty_array; keyword.(*empty_array, a: $x#{block})") # GVAR |
| 814 | + check_allocations(0, 1, "@x = empty_array; keyword.(*empty_array, a: @x#{block})") # IVAR |
| 815 | + check_allocations(0, 1, "self.class.const_set(:X, empty_array); keyword.(*empty_array, a: X#{block})") # CONST |
| 816 | + check_allocations(0, 1, "keyword.(*empty_array, a: Object::X#{block})") # COLON2 |
| 817 | + check_allocations(0, 1, "keyword.(*empty_array, a: ::X#{block})") # COLON3 |
| 818 | + check_allocations(0, 1, "T = keyword; #{'B = block' unless block.empty?}; class Object; @@x = X; T.(*X, a: @@x#{', &B' unless block.empty?}) end") # CVAR |
| 819 | + check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: 1#{block})") # INTEGER |
| 820 | + check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: 1.0#{block})") # FLOAT |
| 821 | + check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: 1.0r#{block})") # RATIONAL |
| 822 | + check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: 1.0i#{block})") # IMAGINARY |
| 823 | + check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: 'a'#{block})") # STR |
| 824 | + check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: :b#{block})") # SYM |
| 825 | + check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: /a/#{block})") # REGX |
| 826 | + check_allocations(0, 1, "keyword.(*empty_array, a: self#{block})") # SELF |
| 827 | + check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: nil#{block})") # NIL |
| 828 | + check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: true#{block})") # TRUE |
| 829 | + check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: false#{block})") # FALSE |
| 830 | + check_allocations(0, 1, "keyword.(*empty_array, a: ->{}#{block})") # LAMBDA |
| 831 | + check_allocations(0, 1, "keyword.(*empty_array, a: $1#{block})") # NTH_REF |
| 832 | + check_allocations(0, 1, "keyword.(*empty_array, a: $`#{block})") # BACK_REF |
| 833 | + RUBY |
| 834 | + end |
| 835 | + |
| 836 | + class WithBlock < self |
| 837 | + def block |
| 838 | + ', &block' |
| 839 | + end |
| 840 | + end |
| 841 | + end |
769 | 842 | end
|
0 commit comments