summaryrefslogtreecommitdiff
path: root/spec/rubyspec/language/yield_spec.rb
diff options
context:
space:
mode:
authoreregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-05-07 12:04:49 +0000
committereregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-05-07 12:04:49 +0000
commit95e8c48dd3348503a8c7db5d0498894a1b676395 (patch)
tree9eef7f720314ebaff56845a74e203770e62284e4 /spec/rubyspec/language/yield_spec.rb
parented7d803500de38186c74bce94d233e85ef51e503 (diff)
Add in-tree mspec and ruby/spec
* For easier modifications of ruby/spec by MRI developers. * .gitignore: track changes under spec. * spec/mspec, spec/rubyspec: add in-tree mspec and ruby/spec. These files can therefore be updated like any other file in MRI. Instructions are provided in spec/README. [Feature #13156] [ruby-core:79246] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58595 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'spec/rubyspec/language/yield_spec.rb')
-rw-r--r--spec/rubyspec/language/yield_spec.rb179
1 files changed, 179 insertions, 0 deletions
diff --git a/spec/rubyspec/language/yield_spec.rb b/spec/rubyspec/language/yield_spec.rb
new file mode 100644
index 0000000000..663110cbe6
--- /dev/null
+++ b/spec/rubyspec/language/yield_spec.rb
@@ -0,0 +1,179 @@
+require File.expand_path('../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/yield', __FILE__)
+
+# Note that these specs use blocks defined as { |*a| ... } to capture the
+# arguments with which the block is invoked. This is slightly confusing
+# because the outer Array is a consequence of |*a| but it is necessary to
+# clearly distinguish some behaviors.
+
+describe "The yield call" do
+ before :each do
+ @y = YieldSpecs::Yielder.new
+ end
+
+ describe "taking no arguments" do
+ it "raises a LocalJumpError when the method is not passed a block" do
+ lambda { @y.z }.should raise_error(LocalJumpError)
+ end
+
+ it "ignores assignment to the explicit block argument and calls the passed block" do
+ @y.ze { 42 }.should == 42
+ end
+ end
+
+ describe "taking a single argument" do
+ describe "when no block is given" do
+ it "raises a LocalJumpError" do
+ lambda { @y.s(1) }.should raise_error(LocalJumpError)
+ end
+ end
+
+ describe "yielding to a literal block" do
+ it "passes an empty Array when the argument is an empty Array" do
+ @y.s([]) { |*a| a }.should == [[]]
+ end
+
+ it "passes nil as a value" do
+ @y.s(nil) { |*a| a }.should == [nil]
+ end
+
+ it "passes a single value" do
+ @y.s(1) { |*a| a }.should == [1]
+ end
+
+ it "passes a single, multi-value Array" do
+ @y.s([1, 2, 3]) { |*a| a }.should == [[1, 2, 3]]
+ end
+ end
+
+ describe "yielding to a lambda" do
+ it "passes an empty Array when the argument is an empty Array" do
+ @y.s([], &lambda { |*a| a }).should == [[]]
+ end
+
+ it "passes nil as a value" do
+ @y.s(nil, &lambda { |*a| a }).should == [nil]
+ end
+
+ it "passes a single value" do
+ @y.s(1, &lambda { |*a| a }).should == [1]
+ end
+
+ it "passes a single, multi-value Array" do
+ @y.s([1, 2, 3], &lambda { |*a| a }).should == [[1, 2, 3]]
+ end
+
+ it "raises an ArgumentError if too few arguments are passed" do
+ lambda {
+ @y.s(1, &lambda { |a,b| [a,b] })
+ }.should raise_error(ArgumentError)
+ end
+
+ ruby_bug "#12705", "2.2"..."2.5" do
+ it "should not destructure an Array into multiple arguments" do
+ lambda {
+ @y.s([1, 2], &lambda { |a,b| [a,b] })
+ }.should raise_error(ArgumentError)
+ end
+ end
+ end
+ end
+
+ describe "taking multiple arguments" do
+ it "raises a LocalJumpError when the method is not passed a block" do
+ lambda { @y.m(1, 2, 3) }.should raise_error(LocalJumpError)
+ end
+
+ it "passes the arguments to the block" do
+ @y.m(1, 2, 3) { |*a| a }.should == [1, 2, 3]
+ end
+
+ it "passes only the first argument if the block takes one parameter" do
+ @y.m(1, 2, 3) { |a| a }.should == 1
+ end
+
+ it "raises an ArgumentError if too many arguments are passed to a lambda" do
+ lambda {
+ @y.m(1, 2, 3, &lambda { |a| })
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if too few arguments are passed to a lambda" do
+ lambda {
+ @y.m(1, 2, 3, &lambda { |a,b,c,d| })
+ }.should raise_error(ArgumentError)
+ end
+ end
+
+ describe "taking a single splatted argument" do
+ it "raises a LocalJumpError when the method is not passed a block" do
+ lambda { @y.r(0) }.should raise_error(LocalJumpError)
+ end
+
+ it "passes a single value" do
+ @y.r(1) { |*a| a }.should == [1]
+ end
+
+ it "passes no arguments when the argument is an empty Array" do
+ @y.r([]) { |*a| a }.should == []
+ end
+
+ it "passes the value when the argument is an Array containing a single value" do
+ @y.r([1]) { |*a| a }.should == [1]
+ end
+
+ it "passes the values of the Array as individual arguments" do
+ @y.r([1, 2, 3]) { |*a| a }.should == [1, 2, 3]
+ end
+
+ it "passes the element of a single element Array" do
+ @y.r([[1, 2]]) { |*a| a }.should == [[1, 2]]
+ @y.r([nil]) { |*a| a }.should == [nil]
+ @y.r([[]]) { |*a| a }.should == [[]]
+ end
+
+ it "passes no values when give nil as an argument" do
+ @y.r(nil) { |*a| a }.should == []
+ end
+ end
+
+ describe "taking multiple arguments with a splat" do
+ it "raises a LocalJumpError when the method is not passed a block" do
+ lambda { @y.rs(1, 2, [3, 4]) }.should raise_error(LocalJumpError)
+ end
+
+ it "passes the arguments to the block" do
+ @y.rs(1, 2, 3) { |*a| a }.should == [1, 2, 3]
+ end
+
+ it "does not pass an argument value if the splatted argument is an empty Array" do
+ @y.rs(1, 2, []) { |*a| a }.should == [1, 2]
+ end
+
+ it "passes the Array elements as arguments if the splatted argument is a non-empty Array" do
+ @y.rs(1, 2, [3]) { |*a| a }.should == [1, 2, 3]
+ @y.rs(1, 2, [nil]) { |*a| a }.should == [1, 2, nil]
+ @y.rs(1, 2, [[]]) { |*a| a }.should == [1, 2, []]
+ @y.rs(1, 2, [3, 4, 5]) { |*a| a }.should == [1, 2, 3, 4, 5]
+ end
+
+ it "does not pass an argument value if the splatted argument is nil" do
+ @y.rs(1, 2, nil) { |*a| a }.should == [1, 2]
+ end
+ end
+
+ describe "taking matching arguments with splats and post args" do
+ it "raises a LocalJumpError when the method is not passed a block" do
+ lambda { @y.rs(1, 2, [3, 4]) }.should raise_error(LocalJumpError)
+ end
+
+ it "passes the arguments to the block" do
+ @y.rs([1, 2], 3, 4) { |(*a, b), c, d| [a, b, c, d] }.should == [[1], 2, 3, 4]
+ end
+ end
+
+ it "uses captured block of a block used in define_method" do
+ @y.deep(2).should == 4
+ end
+
+end