summaryrefslogtreecommitdiff
path: root/spec/ruby/language/pattern_matching_spec.rb
diff options
context:
space:
mode:
authorBenoit Daloze <eregontp@gmail.com>2020-12-27 17:35:32 +0100
committerBenoit Daloze <eregontp@gmail.com>2020-12-27 17:35:32 +0100
commit727c97da1977544c91b9b3677811da3a44af7d53 (patch)
tree4f027117edad10789db57ff4b83242753a89e39d /spec/ruby/language/pattern_matching_spec.rb
parent267bed0cd91711e2a8c79219e97431ba22137b01 (diff)
Update to ruby/spec@4ce9f41
Diffstat (limited to 'spec/ruby/language/pattern_matching_spec.rb')
-rw-r--r--spec/ruby/language/pattern_matching_spec.rb106
1 files changed, 104 insertions, 2 deletions
diff --git a/spec/ruby/language/pattern_matching_spec.rb b/spec/ruby/language/pattern_matching_spec.rb
index edc3826448..dae2828bf6 100644
--- a/spec/ruby/language/pattern_matching_spec.rb
+++ b/spec/ruby/language/pattern_matching_spec.rb
@@ -5,7 +5,7 @@ ruby_version_is "2.7" do
# TODO: Remove excessive eval calls when support of previous version
# Ruby 2.6 will be dropped
- before do
+ before :each do
ScratchPad.record []
end
@@ -41,7 +41,7 @@ ruby_version_is "2.7" do
end
describe "warning" do
- before do
+ before :each do
ruby_version_is ""..."3.0" do
@src = 'case [0, 1]; in [a, b]; end'
end
@@ -49,6 +49,12 @@ ruby_version_is "2.7" do
ruby_version_is "3.0" do
@src = '[0, 1] => [a, b]'
end
+
+ @experimental, Warning[:experimental] = Warning[:experimental], true
+ end
+
+ after :each do
+ Warning[:experimental] = @experimental
end
it "warns about pattern matching is experimental feature" do
@@ -130,6 +136,19 @@ ruby_version_is "2.7" do
}.should raise_error(SyntaxError, /unexpected/)
end
+ it "evaluates the case expression once for multiple patterns, caching the result" do
+ eval(<<~RUBY).should == true
+ case (ScratchPad << :foo; 1)
+ in 0
+ false
+ in 1
+ true
+ end
+ RUBY
+
+ ScratchPad.recorded.should == [:foo]
+ end
+
describe "guards" do
it "supports if guard" do
eval(<<~RUBY).should == false
@@ -508,6 +527,47 @@ ruby_version_is "2.7" do
RUBY
end
+ ruby_version_is "3.0" do
+ it "calls #deconstruct once for multiple patterns, caching the result" do
+ obj = Object.new
+
+ def obj.deconstruct
+ ScratchPad << :deconstruct
+ [0, 1]
+ end
+
+ eval(<<~RUBY).should == true
+ case obj
+ in [1, 2]
+ false
+ in [0, 1]
+ true
+ end
+ RUBY
+
+ ScratchPad.recorded.should == [:deconstruct]
+ end
+ end
+
+ it "calls #deconstruct even on objects that are already an array" do
+ obj = [1, 2]
+ def obj.deconstruct
+ ScratchPad << :deconstruct
+ [3, 4]
+ end
+
+ eval(<<~RUBY).should == true
+ case obj
+ in [3, 4]
+ true
+ else
+ false
+ end
+ RUBY
+
+ ScratchPad.recorded.should == [:deconstruct]
+ end
+
it "does not match object if Constant === object returns false" do
eval(<<~RUBY).should == false
case [0, 1, 2]
@@ -521,6 +581,7 @@ ruby_version_is "2.7" do
it "does not match object without #deconstruct method" do
obj = Object.new
+ obj.should_receive(:respond_to?).with(:deconstruct)
eval(<<~RUBY).should == false
case obj
@@ -546,6 +607,26 @@ ruby_version_is "2.7" do
}.should raise_error(TypeError, /deconstruct must return Array/)
end
+ it "accepts a subclass of Array from #deconstruct" do
+ obj = Object.new
+ def obj.deconstruct
+ subarray = Class.new(Array).new(2)
+ def subarray.[](n)
+ n
+ end
+ subarray
+ end
+
+ eval(<<~RUBY).should == true
+ case obj
+ in [1, 2]
+ false
+ in [0, 1]
+ true
+ end
+ RUBY
+ end
+
it "does not match object if elements of array returned by #deconstruct method does not match elements in pattern" do
obj = Object.new
def obj.deconstruct; [1] end
@@ -778,6 +859,26 @@ ruby_version_is "2.7" do
RUBY
end
+ it "calls #deconstruct_keys per pattern" do
+ obj = Object.new
+
+ def obj.deconstruct_keys(*)
+ ScratchPad << :deconstruct_keys
+ {a: 1}
+ end
+
+ eval(<<~RUBY).should == true
+ case obj
+ in {b: 1}
+ false
+ in {a: 1}
+ true
+ end
+ RUBY
+
+ ScratchPad.recorded.should == [:deconstruct_keys, :deconstruct_keys]
+ end
+
it "does not match object if Constant === object returns false" do
eval(<<~RUBY).should == false
case {a: 1}
@@ -791,6 +892,7 @@ ruby_version_is "2.7" do
it "does not match object without #deconstruct_keys method" do
obj = Object.new
+ obj.should_receive(:respond_to?).with(:deconstruct_keys)
eval(<<~RUBY).should == false
case obj