diff options
author | ktsj <ktsj@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2019-04-17 06:48:03 +0000 |
---|---|---|
committer | ktsj <ktsj@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2019-04-17 06:48:03 +0000 |
commit | 9738f96fcfe50b2a605e350bdd40bd7a85665f54 (patch) | |
tree | a8495fa0a315ef4015f01db4d158b74987d18277 /test | |
parent | b077654a2c89485c086e77c337d30a11ff3781c3 (diff) | |
download | ruby-9738f96fcfe50b2a605e350bdd40bd7a85665f54.tar.gz |
Introduce pattern matching [EXPERIMENTAL]
[ruby-core:87945] [Feature #14912]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67586 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'test')
-rw-r--r-- | test/coverage/test_coverage.rb | 32 | ||||
-rw-r--r-- | test/ripper/test_parser_events.rb | 18 | ||||
-rw-r--r-- | test/ripper/test_sexp.rb | 302 | ||||
-rw-r--r-- | test/ruby/test_pattern_matching.rb | 1075 |
4 files changed, 1427 insertions, 0 deletions
diff --git a/test/coverage/test_coverage.rb b/test/coverage/test_coverage.rb index 30523c341a..f88e97e9d6 100644 --- a/test/coverage/test_coverage.rb +++ b/test/coverage/test_coverage.rb @@ -359,6 +359,38 @@ class TestCoverage < Test::Unit::TestCase end; end + def test_branch_coverage_for_pattern_matching + result = { + :branches=> { + [:case, 0, 3, 4, 8, 7] => {[:in, 1, 5, 6, 5, 7]=>2, [:in, 2, 7, 6, 7, 7]=>0, [:else, 3, 3, 4, 8, 7]=>1}, + [:case, 4, 12, 2, 17, 5] => {[:in, 5, 14, 4, 14, 5]=>2, [:else, 6, 16, 4, 16, 5]=>1}}, + } + assert_coverage(<<~"end;", { branches: true }, result) + def foo(x) + begin + case x + in 0 + 0 + in 1 + 1 + end + rescue NoMatchingPatternError + end + + case x + in 0 + 0 + else + 1 + end + end + + foo(0) + foo(0) + foo(2) + end; + end + def test_branch_coverage_for_safe_method_invocation result = { :branches=>{ diff --git a/test/ripper/test_parser_events.rb b/test/ripper/test_parser_events.rb index be46ad917d..1d2c501c3b 100644 --- a/test/ripper/test_parser_events.rb +++ b/test/ripper/test_parser_events.rb @@ -1509,4 +1509,22 @@ class TestRipper::ParserEvents < Test::Unit::TestCase assert_warn("") {fmt, = warn("\r;")} assert_match(/encountered/, fmt) end + + def test_in + thru_in = false + parse('case 0; in 0; end', :on_in) {thru_in = true} + assert_equal true, thru_in + end + + def test_aryptn + thru_aryptn = false + parse('case 0; in [0]; end', :on_aryptn) {thru_aryptn = true} + assert_equal true, thru_aryptn + end + + def test_hshptn + thru_hshptn = false + parse('case 0; in {a:}; end', :on_hshptn) {thru_hshptn = true} + assert_equal true, thru_hshptn + end end if ripper_test diff --git a/test/ripper/test_sexp.rb b/test/ripper/test_sexp.rb index d63464d5a7..93e40f3bd7 100644 --- a/test/ripper/test_sexp.rb +++ b/test/ripper/test_sexp.rb @@ -140,4 +140,306 @@ eot s, bug15670) end + + pattern_matching_data = { + %q{ case 0; in 0; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, [:@int, "0", [1, 11]], [[:void_stmt]], nil]], + + %q{ case 0; in 0 if a; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:if_mod, [:vcall, [:@ident, "a", [1, 16]]], [:@int, "0", [1, 11]]], + [[:void_stmt]], + nil]], + + %q{ case 0; in 0 unless a; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:unless_mod, [:vcall, [:@ident, "a", [1, 20]]], [:@int, "0", [1, 11]]], + [[:void_stmt]], + nil]], + + %q{ case 0; in a; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, [:var_field, [:@ident, "a", [1, 11]]], [[:void_stmt]], nil]], + + %q{ case 0; in a,; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:aryptn, + nil, + [[:var_field, [:@ident, "a", [1, 11]]]], + [:var_field, nil], + nil], + [[:void_stmt]], + nil]], + + %q{ case 0; in a,b; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:aryptn, + nil, + [[:var_field, [:@ident, "a", [1, 11]]], + [:var_field, [:@ident, "b", [1, 13]]]], + nil, + nil], + [[:void_stmt]], + nil]], + + %q{ case 0; in *a; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:aryptn, nil, nil, [:var_field, [:@ident, "a", [1, 12]]], nil], + [[:void_stmt]], + nil]], + + %q{ case 0; in *a,b; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:aryptn, + nil, + nil, + [:var_field, [:@ident, "a", [1, 12]]], + [[:var_field, [:@ident, "b", [1, 14]]]]], + [[:void_stmt]], + nil]], + + %q{ case 0; in *a,b,c; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:aryptn, + nil, + nil, + [:var_field, [:@ident, "a", [1, 12]]], + [[:var_field, [:@ident, "b", [1, 14]]], + [:var_field, [:@ident, "c", [1, 16]]]]], + [[:void_stmt]], + nil]], + + %q{ case 0; in *; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, [:aryptn, nil, nil, [:var_field, nil], nil], [[:void_stmt]], nil]], + + %q{ case 0; in *,a; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:aryptn, + nil, + nil, + [:var_field, nil], + [[:var_field, [:@ident, "a", [1, 13]]]]], + [[:void_stmt]], + nil]], + + %q{ case 0; in a:,**b; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:hshptn, + nil, + [[[:@label, "a:", [1, 11]], nil]], + [:var_field, [:@ident, "b", [1, 16]]]], + [[:void_stmt]], + nil]], + + %q{ case 0; in **a; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:hshptn, nil, [], [:var_field, [:@ident, "a", [1, 13]]]], + [[:void_stmt]], + nil]], + + %q{ case 0; in **; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, [:hshptn, nil, [], nil], [[:void_stmt]], nil]], + + %q{ case 0; in a: 0; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:hshptn, nil, [[[:@label, "a:", [1, 11]], [:@int, "0", [1, 14]]]], nil], + [[:void_stmt]], + nil]], + + %q{ case 0; in a:; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:hshptn, nil, [[[:@label, "a:", [1, 11]], nil]], nil], + [[:void_stmt]], + nil]], + + %q{ case 0; in "a": 0; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:hshptn, + nil, + [[[:string_content, [:@tstring_content, "a", [1, 12]]], + [:@int, "0", [1, 16]]]], + nil], + [[:void_stmt]], + nil]], + + %q{ case 0; in "a":; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:hshptn, + nil, + [[[:string_content, [:@tstring_content, "a", [1, 12]]], nil]], + nil], + [[:void_stmt]], + nil]], + + %q{ case 0; in a: 0, b: 0; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:hshptn, + nil, + [[[:@label, "a:", [1, 11]], [:@int, "0", [1, 14]]], + [[:@label, "b:", [1, 17]], [:@int, "0", [1, 20]]]], + nil], + [[:void_stmt]], + nil]], + + %q{ case 0; in 0 => a; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:binary, + [:@int, "0", [1, 11]], + :"=>", + [:var_field, [:@ident, "a", [1, 16]]]], + [[:void_stmt]], + nil]], + + %q{ case 0; in 0 | 1; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:binary, [:@int, "0", [1, 11]], :|, [:@int, "1", [1, 15]]], + [[:void_stmt]], + nil]], + + %q{ case 0; in A(0); end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:aryptn, + [:var_ref, [:@const, "A", [1, 11]]], + [[:@int, "0", [1, 13]]], + nil, + nil], + [[:void_stmt]], + nil]], + + %q{ case 0; in A(a:); end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:hshptn, + [:var_ref, [:@const, "A", [1, 11]]], + [[[:@label, "a:", [1, 13]], nil]], + nil], + [[:void_stmt]], + nil]], + + %q{ case 0; in A(); end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:aryptn, [:var_ref, [:@const, "A", [1, 11]]], nil, nil, nil], + [[:void_stmt]], + nil]], + + %q{ case 0; in A[a]; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:aryptn, + [:var_ref, [:@const, "A", [1, 11]]], + [[:var_field, [:@ident, "a", [1, 13]]]], + nil, + nil], + [[:void_stmt]], + nil]], + + %q{ case 0; in A[a:]; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:hshptn, + [:var_ref, [:@const, "A", [1, 11]]], + [[[:@label, "a:", [1, 13]], nil]], + nil], + [[:void_stmt]], + nil]], + + %q{ case 0; in A[]; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:aryptn, [:var_ref, [:@const, "A", [1, 11]]], nil, nil, nil], + [[:void_stmt]], + nil]], + + %q{ case 0; in [a]; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:aryptn, nil, [[:var_field, [:@ident, "a", [1, 12]]]], nil, nil], + [[:void_stmt]], + nil]], + + %q{ case 0; in []; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, [:aryptn, nil, nil, nil, nil], [[:void_stmt]], nil]], + + %q{ case 0; in {a: 0}; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, + [:hshptn, nil, [[[:@label, "a:", [1, 12]], [:@int, "0", [1, 15]]]], nil], + [[:void_stmt]], + nil]], + + %q{ case 0; in {}; end } => + [:case, + [:@int, "0", [1, 5]], + [:in, [:hshptn, nil, nil, nil], [[:void_stmt]], nil]], + + %q{ case 0; in (0); end } => + [:case, + [:@int, "0", [1, 5]], + [:in, [:@int, "0", [1, 12]], [[:void_stmt]], nil]], + + %q{ case 0; in a:, a:; end } => + nil, + + %q{ case 0; in a?:; end } => + nil, + } + pattern_matching_data.each_with_index do |(src, expected), i| + define_method(:"test_pattern_matching_#{i}") do + sexp = Ripper.sexp(src.strip) + assert_equal expected, sexp && sexp[1][0], src + end + end end if ripper_test diff --git a/test/ruby/test_pattern_matching.rb b/test/ruby/test_pattern_matching.rb new file mode 100644 index 0000000000..b0d8e4778b --- /dev/null +++ b/test/ruby/test_pattern_matching.rb @@ -0,0 +1,1075 @@ +# frozen_string_literal: true +require 'test/unit' + +class TestPatternMatching < Test::Unit::TestCase + class C + class << self + attr_accessor :keys + end + + def initialize(obj) + @obj = obj + end + + def deconstruct + @obj + end + + def deconstruct_keys(keys) + C.keys = keys + @obj + end + end + + def test_basic + assert_block do + case 0 + in 0 + true + else + false + end + end + + assert_block do + case 0 + in 1 + false + else + true + end + end + + assert_raise(NoMatchingPatternError) do + case 0 + in 1 + false + end + end + + begin + o = [0] + case o + in 1 + false + end + rescue => e + assert_match o.inspect, e.message + end + + assert_block do + begin + true + ensure + case 0 + in 0 + false + end + end + end + + assert_block do + begin + true + ensure + case 0 + in 1 + else + false + end + end + end + + assert_raise(NoMatchingPatternError) do + begin + ensure + case 0 + in 1 + end + end + end + + assert_block do + eval(%q{ + case true + in a + a + end + }) + end + + assert_block do + tap do |a| + tap do + case true + in a + a + end + end + end + end + + assert_raise(NoMatchingPatternError) do + o = BasicObject.new + def o.match + case 0 + in 1 + end + end + o.match + end + end + + def test_modifier + assert_block do + case 0 + in a if a == 0 + true + end + end + + assert_block do + case 0 + in a if a != 0 + else + true + end + end + + assert_block do + case 0 + in a unless a != 0 + true + end + end + + assert_block do + case 0 + in a unless a == 0 + else + true + end + end + end + + def test_as_pattern + assert_block do + case 0 + in 0 => a + a == 0 + end + end + end + + def test_alternative_pattern + assert_block do + [0, 1].all? do |i| + case i + in 0 | 1 + true + end + end + end + + assert_block do + case 0 + in _ | _a + true + end + end + + assert_syntax_error(%q{ + case 0 + in a | 0 + end + }, /illegal variable in alternative pattern/) + end + + def test_var_pattern + assert_block do + case [0, 1] + in a, a + a == 1 + end + end + end + + def test_literal_value_pattern + assert_block do + case [nil, self, true, false] + in [nil, self, true, false] + true + end + end + + assert_block do + case [0d170, 0D170, 0xaa, 0xAa, 0xAA, 0Xaa, 0XAa, 0XaA, 0252, 0o252, 0O252] + in [0d170, 0D170, 0xaa, 0xAa, 0xAA, 0Xaa, 0XAa, 0XaA, 0252, 0o252, 0O252] + true + end + + case [0b10101010, 0B10101010, 12r, 12.3r, 1i, 12.3ri] + in [0b10101010, 0B10101010, 12r, 12.3r, 1i, 12.3ri] + true + end + end + + assert_block do + x = 'x' + case ['a', 'a', x] + in ['a', "a", "#{x}"] + true + end + end + + assert_block do + case ["a\n"] + in [<<END] +a +END + true + end + end + + assert_block do + case [:a, :"a"] + in [:a, :"a"] + true + end + end + + assert_block do + case [0, 1, 2, 3, 4, 5] + in [0..1, 0...2, 0.., 0..., (...5), (..5)] + true + end + end + + assert_syntax_error(%q{ + case 0 + in a..b + end + }, /unexpected/) + + assert_block do + case 'abc' + in /a/ + true + end + end + + assert_block do + case 0 + in ->(i) { i == 0 } + true + end + end + + assert_block do + case [%(a), %q(a), %Q(a), %w(a), %W(a), %i(a), %I(a), %s(a), %x(echo a), %(), %q(), %Q(), %w(), %W(), %i(), %I(), %s(), 'a'] + in [%(a), %q(a), %Q(a), %w(a), %W(a), %i(a), %I(a), %s(a), %x(echo a), %(), %q(), %Q(), %w(), %W(), %i(), %I(), %s(), %r(a)] + true + end + end + + assert_block do + case [__FILE__, __LINE__ + 1, __ENCODING__] + in [__FILE__, __LINE__, __ENCODING__] + true + end + end + end + + def test_constant_value_pattern + assert_block do + case 0 + in Integer + true + end + end + + assert_block do + case 0 + in Object::Integer + true + end + end + + assert_block do + case 0 + in ::Object::Integer + true + end + end + end + + def test_pin_operator_value_pattern + assert_block do + a = /a/ + case 'abc' + in ^a + true + end + end + + assert_block do + case [0, 0] + in a, ^a + a == 0 + end + end + end + + def test_array_pattern + assert_block do + [[0], C.new([0])].all? do |i| + case i + in 0,; + true + end + end + end + + assert_block do + [[0, 1], C.new([0, 1])].all? do |i| + case i + in 0,; + true + end + end + end + + assert_block do + [[], C.new([])].all? do |i| + case i + in 0,; + else + true + end + end + end + + assert_block do + [[0, 1], C.new([0, 1])].all? do |i| + case i + in 0, 1 + true + end + end + end + + assert_block do + [[0], C.new([0])].all? do |i| + case i + in 0, 1 + else + true + end + end + end + + assert_block do + [[], C.new([])].all? do |i| + case i + in *a + a == [] + end + end + end + + assert_block do + [[0], C.new([0])].all? do |i| + case i + in *a + a == [0] + end + end + end + + assert_block do + [[0], C.new([0])].all? do |i| + case i + in *a, 0, 1 + else + true + end + end + end + + assert_block do + [[0, 1], C.new([0, 1])].all? do |i| + case i + in *a, 0, 1 + a == [] + end + end + end + + assert_block do + [[0, 1, 2], C.new([0, 1, 2])].all? do |i| + case i + in *a, 1, 2 + a == [0] + end + end + end + + assert_block do + [[], C.new([])].all? do |i| + case i + in *; + true + end + end + end + + assert_block do + [[0], C.new([0])].all? do |i| + case i + in *, 0, 1 + else + true + end + end + end + + assert_block do + [[0, 1], C.new([0, 1])].all? do |i| + case i + in *, 0, 1 + true + end + end + end + + assert_block do + [[0, 1, 2], C.new([0, 1, 2])].all? do |i| + case i + in *, 1, 2 + true + end + end + end + + assert_block do + case C.new([0]) + in C(0) + true + end + end + + assert_block do + case C.new([0]) + in Array(0) + else + true + end + end + + assert_block do + case C.new([]) + in C() + true + end + end + + assert_block do + case C.new([]) + in Array() + else + true + end + end + + assert_block do + case C.new([0]) + in C[0] + true + end + end + + assert_block do + case C.new([0]) + in Array[0] + else + true + end + end + + assert_block do + case C.new([]) + in C[] + true + end + end + + assert_block do + case C.new([]) + in Array[] + else + true + end + end + + assert_block do + case [] + in [] + true + end + end + + assert_block do + case C.new([]) + in [] + true + end + end + + assert_block do + case [0] + in [0] + true + end + end + + assert_block do + case C.new([0]) + in [0] + true + end + end + + assert_block do + case [] + in [0, *a] + else + true + end + end + + assert_block do + case [0] + in [0, *a] + a == [] + end + end + + assert_block do + case [0] + in [0, *a, 1] + else + true + end + end + + assert_block do + case [0, 1] + in [0, *a, 1] + a == [] + end + end + + assert_block do + case [0, 1, 2] + in [0, *a, 2] + a == [1] + end + end + + assert_block do + case [] + in [0, *] + else + true + end + end + + assert_block do + case [0] + in [0, *] + true + end + end + + assert_block do + case [0, 1] + in [0, *] + true + end + end + + assert_block do + case [] + in [0, *a] + else + true + end + end + + assert_block do + case [0] + in [0, *a] + a == [] + end + end + + assert_block do + case [0, 1] + in [0, *a] + a == [1] + end + end + end + + def test_hash_pattern + assert_block do + [{}, C.new({})].all? do |i| + case i + in a: 0 + else + true + end + end + end + + assert_block do + [{a: 0}, C.new({a: 0})].all? do |i| + case i + in a: 0 + true + end + end + end + + assert_block do + [{a: 0, b: 1}, C.new({a: 0, b: 1})].all? do |i| + case i + in a: 0 + true + end + end + end + + assert_block do + [{a: 0}, C.new({a: 0})].all? do |i| + case i + in a: 0, b: 1 + else + true + end + end + end + + assert_block do + [{a: 0, b: 1}, C.new({a: 0, b: 1})].all? do |i| + case i + in a: 0, b: 1 + true + end + end + end + + assert_block do + [{a: 0, b: 1, c: 2}, C.new({a: 0, b: 1, c: 2})].all? do |i| + case i + in a: 0, b: 1 + true + end + end + end + + assert_block do + [{}, C.new({})].all? do |i| + case i + in a: + else + true + end + end + end + + assert_block do + [{a: 0}, C.new({a: 0})].all? do |i| + case i + in a: + a == 0 + end + end + end + + assert_block do + [{a: 0, b: 1}, C.new({a: 0, b: 1})].all? do |i| + case i + in a: + a == 0 + end + end + end + + assert_block do + [{a: 0}, C.new({a: 0})].all? do |i| + case i + in "a": 0 + true + end + end + end + + assert_block do + [{a: 0}, C.new({a: 0})].all? do |i| + case i + in "a":; + a == 0 + end + end + end + + assert_block do + [{}, C.new({})].all? do |i| + case i + in **a + a == {} + end + end + end + + assert_block do + [{a: 0}, C.new({a: 0})].all? do |i| + case i + in **a + a == {a: 0} + end + end + end + + assert_block do + [{}, C.new({})].all? do |i| + case i + in **; + true + end + end + end + + assert_block do + [{a: 0}, C.new({a: 0})].all? do |i| + case i + in **; + true + end + end + end + + assert_block do + [{}, C.new({})].all? do |i| + case i + in a:, **b + else + true + end + end + end + + assert_block do + [{a: 0}, C.new({a: 0})].all? do |i| + case i + in a:, **b + a == 0 && b == {} + end + end + end + + assert_block do + [{a: 0, b: 1}, C.new({a: 0, b: 1})].all? do |i| + case i + in a:, **b + a == 0 && b == {b: 1} + end + end + end + + assert_block do + case C.new({a: 0}) + in C(a: 0) + true + end + end + + assert_block do + case {a: 0} + in C(a: 0) + else + true + end + end + + assert_block do + case C.new({a: 0}) + in C[a: 0] + true + end + end + + assert_block do + case {a: 0} + in C[a: 0] + else + true + end + end + + assert_block do + [{}, C.new({})].all? do |i| + case i + in {a: 0} + else + true + end + end + end + + assert_block do + [{a: 0}, C.new({a: 0})].all? do |i| + case i + in {a: 0} + true + end + end + end + + assert_block do + [{a: 0, b: 1}, C.new({a: 0, b: 1})].all? do |i| + case i + in {a: 0} + true + end + end + end + + assert_block do + [{}, C.new({})].all? do |i| + case i + in {} + true + end + end + end + + assert_block do + [{a: 0}, C.new({a: 0})].all? do |i| + case i + in {} + else + true + end + end + end + + assert_syntax_error(%q{ + case _ + in a:, a: + end + }, /duplicated key name/) + + assert_syntax_error(%q{ + case _ + in a?: + end + }, /key must be valid as local variables/) + + assert_block do + case {a?: true} + in a?: true + true + end + end + + assert_syntax_error(%q{ + case _ + in "a-b": + end + }, /key must be valid as local variables/) + + assert_block do + case {"a-b": true} + in "a-b": true + true + end + end + + assert_syntax_error(%q{ + case _ + in "#{a}": a + end + }, /symbol literal with interpolation is not allowed/) + + assert_syntax_error(%q{ + case _ + in "#{a}": + end + }, /symbol literal with interpolation is not allowed/) + end + + def test_paren + assert_block do + case 0 + in (0) + true + end + end + end + + def test_invalid_syntax + assert_syntax_error(%q{ + case 0 + in a, b: + end + }, /unexpected/) + + assert_syntax_error(%q{ + case 0 + in [a:] + end + }, /unexpected/) + + assert_syntax_error(%q{ + case 0 + in {a} + end + }, /unexpected/) + + assert_syntax_error(%q{ + case 0 + in {0 => a} + end + }, /unexpected/) + end + + ################################################################ + + class CTypeError + def deconstruct + nil + end + + def deconstruct_keys(keys) + nil + end + end + + def test_deconstruct + assert_raise(TypeError) do + case CTypeError.new + in [] + end + end + end + + def test_deconstruct_keys + assert_raise(TypeError) do + case CTypeError.new + in {} + end + end + + assert_block do + case {} + in {} + $keys == nil + end + end + + assert_block do + case C.new({a: 0, b: 0, c: 0}) + in {a: 0, b:} + C.keys == [:a, :b] + end + end + + assert_block do + case C.new({a: 0, b: 0, c: 0}) + in {a: 0, b:, **} + C.keys == [:a, :b] + end + end + + assert_block do + case C.new({a: 0, b: 0, c: 0}) + in {a: 0, b:, **r} + C.keys == nil + end + end + + assert_block do + case C.new({a: 0, b: 0, c: 0}) + in {**} + C.keys == [] + end + end + + assert_block do + case C.new({a: 0, b: 0, c: 0}) + in {**r} + C.keys == nil + end + end + end + + ################################################################ + + class TestPatternMatchingRefinements < Test::Unit::TestCase + class C1 + def deconstruct + [:C1] + end + end + + class C2 + end + + module M + refine Array do + def deconstruct + [0] + end + end + + refine Hash do + def deconstruct_keys(_) + {a: 0} + end + end + + refine C2.singleton_class do + def ===(obj) + obj.kind_of?(C1) + end + end + end + + using M + + def test_refinements + assert_block do + case [] + in [0] + true + end + end + + assert_block do + case {} + in {a: 0} + true + end + end + + assert_block do + case C1.new + in C2(:C1) + true + end + end + end + end +end |