summaryrefslogtreecommitdiff
path: root/test/ruby/test_pattern_matching.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/ruby/test_pattern_matching.rb')
-rw-r--r--test/ruby/test_pattern_matching.rb226
1 files changed, 200 insertions, 26 deletions
diff --git a/test/ruby/test_pattern_matching.rb b/test/ruby/test_pattern_matching.rb
index 2fdad78699..cfe3bd1e19 100644
--- a/test/ruby/test_pattern_matching.rb
+++ b/test/ruby/test_pattern_matching.rb
@@ -1,9 +1,26 @@
# frozen_string_literal: true
require 'test/unit'
-experimental, Warning[:experimental] = Warning[:experimental], false # suppress "warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby!"
-eval "\n#{<<~'END_of_GUARD'}", binding, __FILE__, __LINE__
class TestPatternMatching < Test::Unit::TestCase
+ class NullFormatter
+ def message_for(corrections)
+ ""
+ end
+ end
+
+ def setup
+ if defined?(DidYouMean.formatter=nil)
+ @original_formatter = DidYouMean.formatter
+ DidYouMean.formatter = NullFormatter.new
+ end
+ end
+
+ def teardown
+ if defined?(DidYouMean.formatter=nil)
+ DidYouMean.formatter = @original_formatter
+ end
+ end
+
class C
class << self
attr_accessor :keys
@@ -92,16 +109,12 @@ class TestPatternMatching < Test::Unit::TestCase
end
assert_block do
- # suppress "warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby!"
- experimental, Warning[:experimental] = Warning[:experimental], false
eval(%q{
case true
in a
a
end
})
- ensure
- Warning[:experimental] = experimental
end
assert_block do
@@ -341,6 +354,14 @@ END
end
assert_block do
+ a = "abc"
+ case 'abc'
+ in /#{a}/o
+ true
+ end
+ end
+
+ assert_block do
case 0
in ->(i) { i == 0 }
true
@@ -447,6 +468,8 @@ END
true
end
end
+
+ assert_valid_syntax("1 in ^(1\n)")
end
def test_array_pattern
@@ -781,6 +804,10 @@ END
true
end
end
+
+ assert_syntax_error(%q{
+ 0 => [a, *a]
+ }, /duplicated variable name/)
end
def test_find_pattern
@@ -849,6 +876,10 @@ END
false
end
end
+
+ assert_syntax_error(%q{
+ 0 => [*a, a, b, *b]
+ }, /duplicated variable name/)
end
def test_hash_pattern
@@ -1138,6 +1169,28 @@ END
end
end
+ bug18890 = assert_warning(/(?:.*:[47]: warning: possibly useless use of a literal in void context\n){2}/) do
+ eval("#{<<~';;;'}")
+ proc do |i|
+ case i
+ in a:
+ 0 # line 4
+ a
+ in "b":
+ 0 # line 7
+ b
+ else
+ false
+ end
+ end
+ ;;;
+ end
+ [{a: 42}, {b: 42}].each do |i|
+ assert_block('newline should be significant after pattern label') do
+ bug18890.call(i)
+ end
+ end
+
assert_syntax_error(%q{
case _
in a:, a:
@@ -1278,7 +1331,7 @@ END
end
assert_block do
- case {}
+ case C.new({})
in {}
C.keys == nil
end
@@ -1519,33 +1572,154 @@ END
assert_raise(NoMatchingPatternError) do
{a: 1} => {a: 0}
end
- assert_syntax_error("if {} => {a:}; end", /void value expression/)
- assert_syntax_error(%q{
- 1 => a, b
- }, /unexpected/, '[ruby-core:95098]')
- assert_syntax_error(%q{
- 1 => a:
- }, /unexpected/, '[ruby-core:95098]')
+
+ [1, 2] => a, b
+ assert_equal 1, a
+ assert_equal 2, b
+
+ {a: 1} => a:
+ assert_equal 1, a
assert_equal true, (1 in 1)
assert_equal false, (1 in 2)
end
- def assert_experimental_warning(code)
- w = Warning[:experimental]
+ def test_bug18990
+ {a: 0} => a:
+ assert_equal 0, a
+ {a: 0} => a:
+ assert_equal 0, a
+
+ {a: 0} in a:
+ assert_equal 0, a
+ {a: 0} in a:
+ assert_equal 0, a
+ end
+
+ ################################################################
+
+ def test_single_pattern_error_value_pattern
+ assert_raise_with_message(NoMatchingPatternError, "0: 1 === 0 does not return true") do
+ 0 => 1
+ end
+ end
+
+ def test_single_pattern_error_array_pattern
+ assert_raise_with_message(NoMatchingPatternError, "[]: Hash === [] does not return true") do
+ [] => Hash[]
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "0: 0 does not respond to #deconstruct") do
+ 0 => []
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "[0]: [0] length mismatch (given 1, expected 0)") do
+ [0] => []
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "[]: [] length mismatch (given 0, expected 1+)") do
+ [] => [_, *]
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "[0, 0]: 1 === 0 does not return true") do
+ [0, 0] => [0, 1]
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "[0, 0]: 1 === 0 does not return true") do
+ [0, 0] => [*, 0, 1]
+ end
+ end
+
+ def test_single_pattern_error_find_pattern
+ assert_raise_with_message(NoMatchingPatternError, "[]: Hash === [] does not return true") do
+ [] => Hash[*, _, *]
+ end
- Warning[:experimental] = false
- assert_warn('') {eval(code)}
+ assert_raise_with_message(NoMatchingPatternError, "0: 0 does not respond to #deconstruct") do
+ 0 => [*, _, *]
+ end
- Warning[:experimental] = true
- assert_warn(/is experimental/) {eval(code)}
- ensure
- Warning[:experimental] = w
+ assert_raise_with_message(NoMatchingPatternError, "[]: [] length mismatch (given 0, expected 1+)") do
+ [] => [*, _, *]
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "[0]: [0] does not match to find pattern") do
+ [0] => [*, 1, *]
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "[0]: [0] does not match to find pattern") do
+ [0] => [*, {a:}, *]
+ raise a # suppress "unused variable: a" warning
+ end
end
- def test_experimental_warning
- assert_experimental_warning("case [0]; in [*, 0, *]; end")
+ def test_single_pattern_error_hash_pattern
+ assert_raise_with_message(NoMatchingPatternError, "{}: Array === {} does not return true") do
+ {} => Array[a:]
+ raise a # suppress "unused variable: a" warning
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "0: 0 does not respond to #deconstruct_keys") do
+ 0 => {a:}
+ raise a # suppress "unused variable: a" warning
+ end
+
+ assert_raise_with_message(NoMatchingPatternKeyError, "{:a=>0}: key not found: :aa") do
+ {a: 0} => {aa:}
+ raise aa # suppress "unused variable: aa" warning
+ rescue NoMatchingPatternKeyError => e
+ assert_equal({a: 0}, e.matchee)
+ assert_equal(:aa, e.key)
+ raise e
+ end
+
+ assert_raise_with_message(NoMatchingPatternKeyError, "{:a=>{:b=>0}}: key not found: :bb") do
+ {a: {b: 0}} => {a: {bb:}}
+ raise bb # suppress "unused variable: bb" warning
+ rescue NoMatchingPatternKeyError => e
+ assert_equal({b: 0}, e.matchee)
+ assert_equal(:bb, e.key)
+ raise e
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "{:a=>0}: 1 === 0 does not return true") do
+ {a: 0} => {a: 1}
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "{:a=>0}: {:a=>0} is not empty") do
+ {a: 0} => {}
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "[{:a=>0}]: rest of {:a=>0} is not empty") do
+ [{a: 0}] => [{**nil}]
+ end
+ end
+
+ def test_single_pattern_error_as_pattern
+ assert_raise_with_message(NoMatchingPatternError, "[0]: 1 === 0 does not return true") do
+ case [0]
+ in [1] => _
+ end
+ end
+ end
+
+ def test_single_pattern_error_alternative_pattern
+ assert_raise_with_message(NoMatchingPatternError, "0: 2 === 0 does not return true") do
+ 0 => 1 | 2
+ end
+ end
+
+ def test_single_pattern_error_guard_clause
+ assert_raise_with_message(NoMatchingPatternError, "0: guard clause does not return true") do
+ case 0
+ in _ if false
+ end
+ end
+
+ assert_raise_with_message(NoMatchingPatternError, "0: guard clause does not return true") do
+ case 0
+ in _ unless true
+ end
+ end
end
end
-END_of_GUARD
-Warning[:experimental] = experimental