diff options
Diffstat (limited to 'spec/ruby/core/proc')
27 files changed, 628 insertions, 391 deletions
diff --git a/spec/ruby/core/proc/allocate_spec.rb b/spec/ruby/core/proc/allocate_spec.rb index a512c73b1a..96c4eb9fa8 100644 --- a/spec/ruby/core/proc/allocate_spec.rb +++ b/spec/ruby/core/proc/allocate_spec.rb @@ -2,8 +2,8 @@ require_relative '../../spec_helper' describe "Proc.allocate" do it "raises a TypeError" do - lambda { + -> { Proc.allocate - }.should raise_error(TypeError) + }.should.raise(TypeError) end end diff --git a/spec/ruby/core/proc/arity_spec.rb b/spec/ruby/core/proc/arity_spec.rb index f7cb5ad0f8..5c7728cb30 100644 --- a/spec/ruby/core/proc/arity_spec.rb +++ b/spec/ruby/core/proc/arity_spec.rb @@ -268,6 +268,14 @@ describe "Proc#arity" do @a.arity.should == 3 @b.arity.should == 3 end + + # implicit rest + evaluate <<-ruby do + @a = lambda { |a, | } + ruby + + @a.arity.should == 1 + end end context "returns negative values" do @@ -530,6 +538,14 @@ describe "Proc#arity" do @a.arity.should == 1 @b.arity.should == 5 end + + # implicit rest + evaluate <<-ruby do + @a = proc { |a, | } + ruby + + @a.arity.should == 1 + end end context "returns negative values" do diff --git a/spec/ruby/core/proc/binding_spec.rb b/spec/ruby/core/proc/binding_spec.rb index 5e8a461a55..d643cbf89c 100644 --- a/spec/ruby/core/proc/binding_spec.rb +++ b/spec/ruby/core/proc/binding_spec.rb @@ -2,15 +2,15 @@ require_relative '../../spec_helper' describe "Proc#binding" do it "returns a Binding instance" do - [Proc.new{}, lambda {}, proc {}].each { |p| - p.binding.should be_kind_of(Binding) + [Proc.new{}, -> {}, proc {}].each { |p| + p.binding.should.is_a?(Binding) } end it "returns the binding associated with self" do obj = mock('binding') def obj.test_binding(some, params) - lambda {} + -> {} end lambdas_binding = obj.test_binding(1, 2).binding diff --git a/spec/ruby/core/proc/block_pass_spec.rb b/spec/ruby/core/proc/block_pass_spec.rb index 99255139d4..82c08db8a7 100644 --- a/spec/ruby/core/proc/block_pass_spec.rb +++ b/spec/ruby/core/proc/block_pass_spec.rb @@ -8,36 +8,14 @@ describe "Proc as a block pass argument" do it "remains the same object if re-vivified by the target method" do p = Proc.new {} p2 = revivify(&p) - p.should equal p2 + p.should.equal? p2 p.should == p2 end it "remains the same object if reconstructed with Proc.new" do p = Proc.new {} p2 = Proc.new(&p) - p.should equal p2 + p.should.equal? p2 p.should == p2 end end - -ruby_version_is ""..."2.7" do - describe "Proc as an implicit block pass argument" do - def revivify - Proc.new - end - - it "remains the same object if re-vivified by the target method" do - p = Proc.new {} - p2 = revivify(&p) - p.should equal p2 - p.should == p2 - end - - it "remains the same object if reconstructed with Proc.new" do - p = Proc.new {} - p2 = Proc.new(&p) - p.should equal p2 - p.should == p2 - end - end -end diff --git a/spec/ruby/core/proc/clone_spec.rb b/spec/ruby/core/proc/clone_spec.rb index a1a1292654..aee4873e09 100644 --- a/spec/ruby/core/proc/clone_spec.rb +++ b/spec/ruby/core/proc/clone_spec.rb @@ -1,6 +1,28 @@ require_relative '../../spec_helper' +require_relative 'fixtures/common' require_relative 'shared/dup' describe "Proc#clone" do it_behaves_like :proc_dup, :clone + + ruby_bug "cloning a frozen proc is broken on Ruby 3.3", ""..."3.4" do + it "preserves frozen status" do + proc = Proc.new { } + proc.freeze + proc.frozen?.should == true + proc.clone.frozen?.should == true + end + end + + it "calls #initialize_clone on subclass" do + obj = ProcSpecs::MyProc2.new(:a, 2) { } + dup = obj.clone + + dup.should_not.equal?(obj) + dup.class.should == ProcSpecs::MyProc2 + + dup.first.should == :a + dup.second.should == 2 + dup.initializer.should == :clone + end end diff --git a/spec/ruby/core/proc/compose_spec.rb b/spec/ruby/core/proc/compose_spec.rb index f1befe658b..9e9b57e06f 100644 --- a/spec/ruby/core/proc/compose_spec.rb +++ b/spec/ruby/core/proc/compose_spec.rb @@ -1,94 +1,142 @@ require_relative '../../spec_helper' require_relative 'shared/compose' -ruby_version_is "2.6" do - describe "Proc#<<" do - it "returns a Proc that is the composition of self and the passed Proc" do - upcase = proc { |s| s.upcase } - succ = proc { |s| s.succ } +describe "Proc#<<" do + it "returns a Proc that is the composition of self and the passed Proc" do + upcase = proc { |s| s.upcase } + succ = proc { |s| s.succ } - (succ << upcase).call('Ruby').should == "RUBZ" - end + (succ << upcase).call('Ruby').should == "RUBZ" + end + + it "calls passed Proc with arguments and then calls self with result" do + f = proc { |x| x * x } + g = proc { |x| x + x } + + (f << g).call(2).should == 16 + (g << f).call(2).should == 8 + end + + it "accepts any callable object" do + inc = proc { |n| n + 1 } + + double = Object.new + def double.call(n); n * 2; end + + (inc << double).call(3).should == 7 + end - it "calls passed Proc with arguments and then calls self with result" do + it_behaves_like :proc_compose, :<<, -> { proc { |s| s.upcase } } + + describe "composition" do + it "is a Proc" do f = proc { |x| x * x } g = proc { |x| x + x } - (f << g).call(2).should == 16 - (g << f).call(2).should == 8 + (f << g).is_a?(Proc).should == true + (f << g).should_not.lambda? end - it "accepts any callable object" do - inc = proc { |n| n + 1 } + it "is a lambda when parameter is lambda" do + f = -> x { x * x } + g = proc { |x| x + x } + lambda_proc = -> x { x } + + # lambda << proc + (f << g).is_a?(Proc).should == true + (f << g).should_not.lambda? - double = Object.new - def double.call(n); n * 2; end + # lambda << lambda + (f << lambda_proc).is_a?(Proc).should == true + (f << lambda_proc).should.lambda? - (inc << double).call(3).should == 7 + # proc << lambda + (g << f).is_a?(Proc).should == true + (g << f).should.lambda? end - it_behaves_like :proc_compose, :<<, -> { proc { |s| s.upcase } } + it "may accept multiple arguments" do + inc = proc { |n| n + 1 } + mul = proc { |n, m| n * m } - describe "composition" do - it "is a Proc" do - f = proc { |x| x * x } - g = proc { |x| x + x } + (inc << mul).call(2, 3).should == 7 + end - (f << g).is_a?(Proc).should == true - (f << g).lambda?.should == false - end + it "passes blocks to the second proc" do + ScratchPad.record [] + one = proc { |&arg| arg.call :one if arg } + two = proc { |&arg| arg.call :two if arg } + (one << two).call { |x| ScratchPad << x } + ScratchPad.recorded.should == [:two] + end + end +end - it "may accept multiple arguments" do - inc = proc { |n| n + 1 } - mul = proc { |n, m| n * m } +describe "Proc#>>" do + it "returns a Proc that is the composition of self and the passed Proc" do + upcase = proc { |s| s.upcase } + succ = proc { |s| s.succ } - (inc << mul).call(2, 3).should == 7 - end - end + (succ >> upcase).call('Ruby').should == "RUBZ" end - describe "Proc#>>" do - it "returns a Proc that is the composition of self and the passed Proc" do - upcase = proc { |s| s.upcase } - succ = proc { |s| s.succ } + it "calls passed Proc with arguments and then calls self with result" do + f = proc { |x| x * x } + g = proc { |x| x + x } - (succ >> upcase).call('Ruby').should == "RUBZ" - end + (f >> g).call(2).should == 8 + (g >> f).call(2).should == 16 + end + + it "accepts any callable object" do + inc = proc { |n| n + 1 } + + double = Object.new + def double.call(n); n * 2; end + + (inc >> double).call(3).should == 8 + end - it "calls passed Proc with arguments and then calls self with result" do + it_behaves_like :proc_compose, :>>, -> { proc { |s| s.upcase } } + + describe "composition" do + it "is a Proc" do f = proc { |x| x * x } g = proc { |x| x + x } - (f >> g).call(2).should == 8 - (g >> f).call(2).should == 16 + (f >> g).is_a?(Proc).should == true + (f >> g).should_not.lambda? end - it "accepts any callable object" do - inc = proc { |n| n + 1 } - - double = Object.new - def double.call(n); n * 2; end + it "is a Proc when other is lambda" do + f = proc { |x| x * x } + g = -> x { x + x } - (inc >> double).call(3).should == 8 + (f >> g).is_a?(Proc).should == true + (f >> g).should_not.lambda? end - it_behaves_like :proc_compose, :>>, -> { proc { |s| s.upcase } } + it "is a lambda when self is lambda" do + f = -> x { x * x } + g = proc { |x| x + x } - describe "composition" do - it "is a Proc" do - f = proc { |x| x * x } - g = proc { |x| x + x } + (f >> g).is_a?(Proc).should == true + (f >> g).should.lambda? + end - (f >> g).is_a?(Proc).should == true - (f >> g).lambda?.should == false - end + it "may accept multiple arguments" do + inc = proc { |n| n + 1 } + mul = proc { |n, m| n * m } - it "may accept multiple arguments" do - inc = proc { |n| n + 1 } - mul = proc { |n, m| n * m } + (mul >> inc).call(2, 3).should == 7 + end - (mul >> inc).call(2, 3).should == 7 - end + it "passes blocks to the first proc" do + ScratchPad.record [] + one = proc { |&arg| arg.call :one if arg } + two = proc { |&arg| arg.call :two if arg } + (one >> two).call { |x| ScratchPad << x } + ScratchPad.recorded.should == [:one] end end end diff --git a/spec/ruby/core/proc/curry_spec.rb b/spec/ruby/core/proc/curry_spec.rb index 7d1da441f1..de13983ca6 100644 --- a/spec/ruby/core/proc/curry_spec.rb +++ b/spec/ruby/core/proc/curry_spec.rb @@ -3,17 +3,17 @@ require_relative '../../spec_helper' describe "Proc#curry" do before :each do @proc_add = Proc.new {|x,y,z| (x||0) + (y||0) + (z||0) } - @lambda_add = lambda {|x,y,z| (x||0) + (y||0) + (z||0) } + @lambda_add = -> x, y, z { (x||0) + (y||0) + (z||0) } end it "returns a Proc when called on a proc" do p = proc { true } - p.curry.should be_an_instance_of(Proc) + p.curry.should.instance_of?(Proc) end it "returns a Proc when called on a lambda" do - p = lambda { true } - p.curry.should be_an_instance_of(Proc) + p = -> { true } + p.curry.should.instance_of?(Proc) end it "calls the curried proc with the arguments if sufficient arguments have been given" do @@ -23,11 +23,11 @@ describe "Proc#curry" do it "returns a Proc that consumes the remainder of the arguments unless sufficient arguments have been given" do proc2 = @proc_add.curry[1][2] - proc2.should be_an_instance_of(Proc) + proc2.should.instance_of?(Proc) proc2.call(3).should == 6 lambda2 = @lambda_add.curry[1][2] - lambda2.should be_an_instance_of(Proc) + lambda2.should.instance_of?(Proc) lambda2.call(3).should == 6 @proc_add.curry.call(1,2,3).should == 6 @@ -36,10 +36,10 @@ describe "Proc#curry" do it "can be called multiple times on the same Proc" do @proc_add.curry - lambda { @proc_add.curry }.should_not raise_error + -> { @proc_add.curry }.should_not.raise @lambda_add.curry - lambda { @lambda_add.curry }.should_not raise_error + -> { @lambda_add.curry }.should_not.raise end it "can be passed superfluous arguments if created from a proc" do @@ -49,21 +49,21 @@ describe "Proc#curry" do end it "raises an ArgumentError if passed superfluous arguments when created from a lambda" do - lambda { @lambda_add.curry[1,2,3,4] }.should raise_error(ArgumentError) - lambda { @lambda_add.curry[1,2].curry[3,4,5,6] }.should raise_error(ArgumentError) + -> { @lambda_add.curry[1,2,3,4] }.should.raise(ArgumentError) + -> { @lambda_add.curry[1,2].curry[3,4,5,6] }.should.raise(ArgumentError) end it "returns Procs with arities of -1" do @proc_add.curry.arity.should == -1 @lambda_add.curry.arity.should == -1 - l = lambda { |*a| } + l = -> *a { } l.curry.arity.should == -1 end it "produces Procs that raise ArgumentError for #binding" do - lambda do + -> do @proc_add.curry.binding - end.should raise_error(ArgumentError) + end.should.raise(ArgumentError) end it "produces Procs that return [[:rest]] for #parameters" do @@ -81,7 +81,7 @@ describe "Proc#curry" do end it "combines arguments and calculates incoming arity accurately for successively currying" do - l = lambda{|a,b,c| a+b+c } + l = -> a, b, c { a+b+c } l1 = l.curry.call(1) # the l1 currying seems unnecessary, but it triggered the original issue l2 = l1.curry.call(2) @@ -93,46 +93,46 @@ end describe "Proc#curry with arity argument" do before :each do - @proc_add = proc {|x,y,z| (x||0) + (y||0) + (z||0) } - @lambda_add = lambda {|x,y,z| (x||0) + (y||0) + (z||0) } + @proc_add = proc { |x,y,z| (x||0) + (y||0) + (z||0) } + @lambda_add = -> x, y, z { (x||0) + (y||0) + (z||0) } end it "accepts an optional Integer argument for the arity" do - lambda { @proc_add.curry(3) }.should_not raise_error - lambda { @lambda_add.curry(3) }.should_not raise_error + -> { @proc_add.curry(3) }.should_not.raise + -> { @lambda_add.curry(3) }.should_not.raise end it "returns a Proc when called on a proc" do - @proc_add.curry(3).should be_an_instance_of(Proc) + @proc_add.curry(3).should.instance_of?(Proc) end it "returns a Proc when called on a lambda" do - @lambda_add.curry(3).should be_an_instance_of(Proc) + @lambda_add.curry(3).should.instance_of?(Proc) end # [ruby-core:24127] it "retains the lambda-ness of the Proc on which its called" do - @lambda_add.curry(3).lambda?.should be_true - @proc_add.curry(3).lambda?.should be_false + @lambda_add.curry(3).lambda?.should == true + @proc_add.curry(3).lambda?.should == false end it "raises an ArgumentError if called on a lambda that requires more than _arity_ arguments" do - lambda { @lambda_add.curry(2) }.should raise_error(ArgumentError) - lambda { lambda{|x, y, z, *more|}.curry(2) }.should raise_error(ArgumentError) + -> { @lambda_add.curry(2) }.should.raise(ArgumentError) + -> { -> x, y, z, *more{}.curry(2) }.should.raise(ArgumentError) end it 'returns a Proc if called on a lambda that requires fewer than _arity_ arguments but may take more' do - lambda{|a, b, c, d=nil, e=nil|}.curry(4).should be_an_instance_of(Proc) - lambda{|a, b, c, d=nil, *e|}.curry(4).should be_an_instance_of(Proc) - lambda{|a, b, c, *d|}.curry(4).should be_an_instance_of(Proc) + -> a, b, c, d=nil, e=nil {}.curry(4).should.instance_of?(Proc) + -> a, b, c, d=nil, *e {}.curry(4).should.instance_of?(Proc) + -> a, b, c, *d {}.curry(4).should.instance_of?(Proc) end it "raises an ArgumentError if called on a lambda that requires fewer than _arity_ arguments" do - lambda { @lambda_add.curry(4) }.should raise_error(ArgumentError) - lambda { lambda { true }.curry(1) }.should raise_error(ArgumentError) - lambda { lambda {|a, b=nil|}.curry(5) }.should raise_error(ArgumentError) - lambda { lambda {|a, &b|}.curry(2) }.should raise_error(ArgumentError) - lambda { lambda {|a, b=nil, &c|}.curry(3) }.should raise_error(ArgumentError) + -> { @lambda_add.curry(4) }.should.raise(ArgumentError) + -> { -> { true }.curry(1) }.should.raise(ArgumentError) + -> { -> a, b=nil {}.curry(5) }.should.raise(ArgumentError) + -> { -> a, &b {}.curry(2) }.should.raise(ArgumentError) + -> { -> a, b=nil, &c {}.curry(3) }.should.raise(ArgumentError) end it "calls the curried proc with the arguments if _arity_ arguments have been given" do @@ -142,39 +142,38 @@ describe "Proc#curry with arity argument" do it "returns a Proc that consumes the remainder of the arguments when fewer than _arity_ arguments are given" do proc2 = @proc_add.curry(3)[1][2] - proc2.should be_an_instance_of(Proc) + proc2.should.instance_of?(Proc) proc2.call(3).should == 6 lambda2 = @lambda_add.curry(3)[1][2] - lambda2.should be_an_instance_of(Proc) + lambda2.should.instance_of?(Proc) lambda2.call(3).should == 6 end it "can be specified multiple times on the same Proc" do @proc_add.curry(2) - lambda { @proc_add.curry(1) }.should_not raise_error + -> { @proc_add.curry(1) }.should_not.raise @lambda_add.curry(3) - lambda { @lambda_add.curry(3) }.should_not raise_error + -> { @lambda_add.curry(3) }.should_not.raise end it "can be passed more than _arity_ arguments if created from a proc" do - lambda { @proc_add.curry(3)[1,2,3,4].should == 6 }.should_not - raise_error(ArgumentError) - lambda { @proc_add.curry(1)[1,2].curry(3)[3,4,5,6].should == 6 }.should_not - raise_error(ArgumentError) + @proc_add.curry(3)[1,2,3,4].should == 6 + + @proc_add.curry(3)[1,2].curry(3)[3,4,5,6].should == 6 end it "raises an ArgumentError if passed more than _arity_ arguments when created from a lambda" do - lambda { @lambda_add.curry(3)[1,2,3,4] }.should raise_error(ArgumentError) - lambda { @lambda_add.curry(1)[1,2].curry(3)[3,4,5,6] }.should raise_error(ArgumentError) + -> { @lambda_add.curry(3)[1,2,3,4] }.should.raise(ArgumentError) + -> { @lambda_add.curry(3)[1,2].curry(3)[3,4,5,6] }.should.raise(ArgumentError) end it "returns Procs with arities of -1 regardless of the value of _arity_" do @proc_add.curry(1).arity.should == -1 @proc_add.curry(2).arity.should == -1 @lambda_add.curry(3).arity.should == -1 - l = lambda { |*a| } + l = -> *a { } l.curry(3).arity.should == -1 end end diff --git a/spec/ruby/core/proc/dup_spec.rb b/spec/ruby/core/proc/dup_spec.rb index 6da2f3080c..8604389422 100644 --- a/spec/ruby/core/proc/dup_spec.rb +++ b/spec/ruby/core/proc/dup_spec.rb @@ -1,6 +1,26 @@ require_relative '../../spec_helper' +require_relative 'fixtures/common' require_relative 'shared/dup' describe "Proc#dup" do it_behaves_like :proc_dup, :dup + + it "resets frozen status" do + proc = Proc.new { } + proc.freeze + proc.frozen?.should == true + proc.dup.frozen?.should == false + end + + it "calls #initialize_dup on subclass" do + obj = ProcSpecs::MyProc2.new(:a, 2) { } + dup = obj.dup + + dup.should_not.equal?(obj) + dup.class.should == ProcSpecs::MyProc2 + + dup.first.should == :a + dup.second.should == 2 + dup.initializer.should == :dup + end end diff --git a/spec/ruby/core/proc/element_reference_spec.rb b/spec/ruby/core/proc/element_reference_spec.rb index f60ae1b086..ea3a915a11 100644 --- a/spec/ruby/core/proc/element_reference_spec.rb +++ b/spec/ruby/core/proc/element_reference_spec.rb @@ -17,13 +17,11 @@ describe "Proc#call on a Proc created with Kernel#lambda or Kernel#proc" do it_behaves_like :proc_call_on_proc_or_lambda, :call end -ruby_bug "#15118", ""..."2.6" do - describe "Proc#[] with frozen_string_literals" do - it "doesn't duplicate frozen strings" do - ProcArefSpecs.aref.frozen?.should be_false - ProcArefSpecs.aref_freeze.frozen?.should be_true - ProcArefFrozenSpecs.aref.frozen?.should be_true - ProcArefFrozenSpecs.aref_freeze.frozen?.should be_true - end +describe "Proc#[] with frozen_string_literal: true/false" do + it "doesn't duplicate frozen strings" do + ProcArefSpecs.aref.frozen?.should == false + ProcArefSpecs.aref_freeze.frozen?.should == true + ProcArefFrozenSpecs.aref.frozen?.should == true + ProcArefFrozenSpecs.aref_freeze.frozen?.should == true end end diff --git a/spec/ruby/core/proc/eql_spec.rb b/spec/ruby/core/proc/eql_spec.rb index a3c5a5658d..ad8f6749fc 100644 --- a/spec/ruby/core/proc/eql_spec.rb +++ b/spec/ruby/core/proc/eql_spec.rb @@ -2,5 +2,5 @@ require_relative '../../spec_helper' require_relative 'shared/equal' describe "Proc#eql?" do - it_behaves_like :proc_equal_undefined, :eql? + it_behaves_like :proc_equal, :eql? end diff --git a/spec/ruby/core/proc/equal_value_spec.rb b/spec/ruby/core/proc/equal_value_spec.rb index 1b6ac792cf..ec7f274732 100644 --- a/spec/ruby/core/proc/equal_value_spec.rb +++ b/spec/ruby/core/proc/equal_value_spec.rb @@ -2,5 +2,5 @@ require_relative '../../spec_helper' require_relative 'shared/equal' describe "Proc#==" do - it_behaves_like :proc_equal_undefined, :== + it_behaves_like :proc_equal, :== end diff --git a/spec/ruby/core/proc/fixtures/common.rb b/spec/ruby/core/proc/fixtures/common.rb index 6e27a2dee7..dfe67d7ba8 100644 --- a/spec/ruby/core/proc/fixtures/common.rb +++ b/spec/ruby/core/proc/fixtures/common.rb @@ -32,7 +32,28 @@ module ProcSpecs @second = b end - attr_reader :first, :second + attr_reader :first, :second, :initializer + + def initialize_copy(other) + super + @initializer = :copy + @first = other.first + @second = other.second + end + + def initialize_dup(other) + super + @initializer = :dup + @first = other.first + @second = other.second + end + + def initialize_clone(other, **options) + super + @initializer = :clone + @first = other.first + @second = other.second + end end class Arity diff --git a/spec/ruby/core/proc/fixtures/proc_aref.rb b/spec/ruby/core/proc/fixtures/proc_aref.rb index a305667797..8ee355b14c 100644 --- a/spec/ruby/core/proc/fixtures/proc_aref.rb +++ b/spec/ruby/core/proc/fixtures/proc_aref.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: false module ProcArefSpecs def self.aref proc {|a| a }["sometext"] diff --git a/spec/ruby/core/proc/fixtures/source_location.rb b/spec/ruby/core/proc/fixtures/source_location.rb index 468262e02a..5572094630 100644 --- a/spec/ruby/core/proc/fixtures/source_location.rb +++ b/spec/ruby/core/proc/fixtures/source_location.rb @@ -5,7 +5,7 @@ module ProcSpecs end def self.my_lambda - lambda { true } + -> { true } end def self.my_proc_new @@ -24,7 +24,7 @@ module ProcSpecs end def self.my_multiline_lambda - lambda do + -> do 'a'.upcase 1 + 22 end @@ -43,8 +43,8 @@ module ProcSpecs end def self.my_detached_lambda - body = lambda { true } - lambda(&body) + body = -> { true } + suppress_warning {lambda(&body)} end def self.my_detached_proc_new diff --git a/spec/ruby/core/proc/hash_spec.rb b/spec/ruby/core/proc/hash_spec.rb index 5993ad5098..adcb1ccb78 100644 --- a/spec/ruby/core/proc/hash_spec.rb +++ b/spec/ruby/core/proc/hash_spec.rb @@ -2,12 +2,12 @@ require_relative '../../spec_helper' describe "Proc#hash" do it "is provided" do - proc {}.respond_to?(:hash).should be_true - lambda {}.respond_to?(:hash).should be_true + proc {}.respond_to?(:hash).should == true + -> {}.respond_to?(:hash).should == true end it "returns an Integer" do - proc { 1 + 489 }.hash.should be_kind_of(Fixnum) + proc { 1 + 489 }.hash.should.is_a?(Integer) end it "is stable" do diff --git a/spec/ruby/core/proc/lambda_spec.rb b/spec/ruby/core/proc/lambda_spec.rb index edf2151f27..1ff6147319 100644 --- a/spec/ruby/core/proc/lambda_spec.rb +++ b/spec/ruby/core/proc/lambda_spec.rb @@ -3,58 +3,53 @@ require_relative 'fixtures/common' describe "Proc#lambda?" do it "returns true if the Proc was created from a block with the lambda keyword" do - lambda {}.lambda?.should be_true + -> {}.lambda?.should == true end it "returns false if the Proc was created from a block with the proc keyword" do - proc {}.lambda?.should be_false + proc {}.lambda?.should == false end it "returns false if the Proc was created from a block with Proc.new" do - Proc.new {}.lambda?.should be_false - end - - it "is preserved when passing a Proc with & to the lambda keyword" do - lambda(&lambda{}).lambda?.should be_true - lambda(&proc{}).lambda?.should be_false + Proc.new {}.lambda?.should == false end it "is preserved when passing a Proc with & to the proc keyword" do - proc(&lambda{}).lambda?.should be_true - proc(&proc{}).lambda?.should be_false + proc(&->{}).lambda?.should == true + proc(&proc{}).lambda?.should == false end it "is preserved when passing a Proc with & to Proc.new" do - Proc.new(&lambda{}).lambda?.should be_true - Proc.new(&proc{}).lambda?.should be_false + Proc.new(&->{}).lambda?.should == true + Proc.new(&proc{}).lambda?.should == false end it "returns false if the Proc was created from a block with &" do - ProcSpecs.new_proc_from_amp{}.lambda?.should be_false + ProcSpecs.new_proc_from_amp{}.lambda?.should == false end it "is preserved when the Proc was passed using &" do - ProcSpecs.new_proc_from_amp(&lambda{}).lambda?.should be_true - ProcSpecs.new_proc_from_amp(&proc{}).lambda?.should be_false - ProcSpecs.new_proc_from_amp(&Proc.new{}).lambda?.should be_false + ProcSpecs.new_proc_from_amp(&->{}).lambda?.should == true + ProcSpecs.new_proc_from_amp(&proc{}).lambda?.should == false + ProcSpecs.new_proc_from_amp(&Proc.new{}).lambda?.should == false end it "returns true for a Method converted to a Proc" do m = :foo.method(:to_s) - m.to_proc.lambda?.should be_true - ProcSpecs.new_proc_from_amp(&m).lambda?.should be_true + m.to_proc.lambda?.should == true + ProcSpecs.new_proc_from_amp(&m).lambda?.should == true end # [ruby-core:24127] it "is preserved when a Proc is curried" do - lambda{}.curry.lambda?.should be_true - proc{}.curry.lambda?.should be_false - Proc.new{}.curry.lambda?.should be_false + ->{}.curry.lambda?.should == true + proc{}.curry.lambda?.should == false + Proc.new{}.curry.lambda?.should == false end it "is preserved when a curried Proc is called without enough arguments" do - lambda{|x,y|}.curry.call(42).lambda?.should be_true - proc{|x,y|}.curry.call(42).lambda?.should be_false - Proc.new{|x,y|}.curry.call(42).lambda?.should be_false + -> x, y{}.curry.call(42).lambda?.should == true + proc{|x,y|}.curry.call(42).lambda?.should == false + Proc.new{|x,y|}.curry.call(42).lambda?.should == false end end diff --git a/spec/ruby/core/proc/new_spec.rb b/spec/ruby/core/proc/new_spec.rb index 1c37c64478..f0b817f0cb 100644 --- a/spec/ruby/core/proc/new_spec.rb +++ b/spec/ruby/core/proc/new_spec.rb @@ -71,7 +71,7 @@ describe "Proc.new with an associated block" do end res = some_method() - lambda { res.call }.should raise_error(LocalJumpError) + -> { res.call }.should.raise(LocalJumpError) end it "returns from within enclosing method when 'return' is used in the block" do @@ -86,7 +86,7 @@ describe "Proc.new with an associated block" do it "returns a subclass of Proc" do obj = ProcSpecs::MyProc.new { } - obj.should be_kind_of(ProcSpecs::MyProc) + obj.should.is_a?(ProcSpecs::MyProc) end it "calls initialize on the Proc object" do @@ -94,20 +94,6 @@ describe "Proc.new with an associated block" do obj.first.should == :a obj.second.should == 2 end - - ruby_version_is ""..."2.7" do - it "returns a new Proc instance from the block passed to the containing method" do - prc = ProcSpecs.new_proc_in_method { "hello" } - prc.should be_an_instance_of(Proc) - prc.call.should == "hello" - end - - it "returns a new Proc instance from the block passed to the containing method" do - prc = ProcSpecs.new_proc_subclass_in_method { "hello" } - prc.should be_an_instance_of(ProcSpecs::ProcSubclass) - prc.call.should == "hello" - end - end end describe "Proc.new with a block argument" do @@ -115,7 +101,7 @@ describe "Proc.new with a block argument" do passed_prc = Proc.new { "hello".size } prc = Proc.new(&passed_prc) - prc.should equal(passed_prc) + prc.should.equal?(passed_prc) prc.call.should == 5 end @@ -124,7 +110,7 @@ describe "Proc.new with a block argument" do passed_prc = Proc.new(&method) prc = Proc.new(&passed_prc) - prc.should equal(passed_prc) + prc.should.equal?(passed_prc) prc.call.should == 5 end @@ -132,7 +118,7 @@ describe "Proc.new with a block argument" do passed_prc = Proc.new(&:size) prc = Proc.new(&passed_prc) - prc.should equal(passed_prc) + prc.should.equal?(passed_prc) prc.call("hello").should == 5 end end @@ -143,7 +129,7 @@ describe "Proc.new with a block argument called indirectly from a subclass" do passed_prc.class.should == ProcSpecs::MyProc prc = ProcSpecs::MyProc.new(&passed_prc) - prc.should equal(passed_prc) + prc.should.equal?(passed_prc) prc.call.should == 5 end @@ -153,7 +139,7 @@ describe "Proc.new with a block argument called indirectly from a subclass" do passed_prc.class.should == ProcSpecs::MyProc prc = ProcSpecs::MyProc.new(&passed_prc) - prc.should equal(passed_prc) + prc.should.equal?(passed_prc) prc.call.should == 5 end @@ -162,54 +148,31 @@ describe "Proc.new with a block argument called indirectly from a subclass" do passed_prc.class.should == ProcSpecs::MyProc prc = ProcSpecs::MyProc.new(&passed_prc) - prc.should equal(passed_prc) + prc.should.equal?(passed_prc) prc.call("hello").should == 5 end end describe "Proc.new without a block" do it "raises an ArgumentError" do - lambda { Proc.new }.should raise_error(ArgumentError) + -> { Proc.new }.should.raise(ArgumentError) end it "raises an ArgumentError if invoked from within a method with no block" do - lambda { ProcSpecs.new_proc_in_method }.should raise_error(ArgumentError) + -> { ProcSpecs.new_proc_in_method }.should.raise(ArgumentError) end it "raises an ArgumentError if invoked on a subclass from within a method with no block" do - lambda { ProcSpecs.new_proc_subclass_in_method }.should raise_error(ArgumentError) - end - - ruby_version_is ""..."2.7" do - it "uses the implicit block from an enclosing method" do - def some_method - Proc.new - end - - prc = some_method { "hello" } - - prc.call.should == "hello" - end + -> { ProcSpecs.new_proc_subclass_in_method }.should.raise(ArgumentError) end - ruby_version_is "2.7" do - it "can be created if invoked from within a method with a block" do - lambda { ProcSpecs.new_proc_in_method { "hello" } }.should complain(/tried to create Proc object without a block/) - end - - it "can be created if invoked on a subclass from within a method with a block" do - lambda { ProcSpecs.new_proc_subclass_in_method { "hello" } }.should complain(/tried to create Proc object without a block/) + it "raises an ArgumentError when passed no block" do + def some_method + Proc.new end - - it "can be create when called with no block" do - def some_method - Proc.new - end - - -> { - some_method { "hello" } - }.should complain(/tried to create Proc object without a block/) - end + -> { ProcSpecs.new_proc_in_method { "hello" } }.should.raise(ArgumentError, 'tried to create Proc object without a block') + -> { ProcSpecs.new_proc_subclass_in_method { "hello" } }.should.raise(ArgumentError, 'tried to create Proc object without a block') + -> { some_method { "hello" } }.should.raise(ArgumentError, 'tried to create Proc object without a block') end end diff --git a/spec/ruby/core/proc/parameters_spec.rb b/spec/ruby/core/proc/parameters_spec.rb index 4a8958497d..ac8c6e3560 100644 --- a/spec/ruby/core/proc/parameters_spec.rb +++ b/spec/ruby/core/proc/parameters_spec.rb @@ -7,8 +7,8 @@ describe "Proc#parameters" do it "returns an Array of Arrays for a proc expecting parameters" do p = proc {|x| } - p.parameters.should be_an_instance_of(Array) - p.parameters.first.should be_an_instance_of(Array) + p.parameters.should.instance_of?(Array) + p.parameters.first.should.instance_of?(Array) end it "sets the first element of each sub-Array to :opt for optional arguments" do @@ -20,55 +20,78 @@ describe "Proc#parameters" do proc {|x| }.parameters.first.first.should == :opt end + it "sets the first element of each sub-Array to :req for required argument if lambda keyword used" do + proc {|x| }.parameters(lambda: true).first.first.should == :req + proc {|y,*x| }.parameters(lambda: true).first.first.should == :req + end + + it "regards named parameters in procs as required if lambda keyword used" do + proc {|x| }.parameters(lambda: true).first.first.should == :req + end + + it "regards named parameters in lambda as optional if lambda: false keyword used" do + -> x { }.parameters(lambda: false).first.first.should == :opt + end + + it "regards named parameters in procs and lambdas as required if lambda keyword is truthy" do + proc {|x| }.parameters(lambda: 123).first.first.should == :req + -> x { }.parameters(lambda: 123).first.first.should == :req + end + + it "ignores the lambda keyword if it is nil" do + proc {|x|}.parameters(lambda: nil).first.first.should == :opt + -> x { }.parameters(lambda: nil).first.first.should == :req + end + it "regards optional keyword parameters in procs as optional" do proc {|x: :y| }.parameters.first.first.should == :key end it "regards parameters with default values as optional" do - lambda {|x=1| }.parameters.first.first.should == :opt + -> x=1 { }.parameters.first.first.should == :opt proc {|x=1| }.parameters.first.first.should == :opt end it "sets the first element of each sub-Array to :req for required arguments" do - lambda {|x,y=[]| }.parameters.first.first.should == :req - lambda {|y,*x| }.parameters.first.first.should == :req + -> x, y=[] { }.parameters.first.first.should == :req + -> y, *x { }.parameters.first.first.should == :req end it "regards named parameters in lambdas as required" do - lambda {|x| }.parameters.first.first.should == :req + -> x { }.parameters.first.first.should == :req end it "regards keyword parameters in lambdas as required" do - eval("lambda {|x:| }").parameters.first.first.should == :keyreq + -> x: { }.parameters.first.first.should == :keyreq end it "sets the first element of each sub-Array to :rest for parameters prefixed with asterisks" do - lambda {|*x| }.parameters.first.first.should == :rest - lambda {|x,*y| }.parameters.last.first.should == :rest + -> *x { }.parameters.first.first.should == :rest + -> x, *y { }.parameters.last.first.should == :rest proc {|*x| }.parameters.first.first.should == :rest proc {|x,*y| }.parameters.last.first.should == :rest end it "sets the first element of each sub-Array to :keyrest for parameters prefixed with double asterisks" do - lambda {|**x| }.parameters.first.first.should == :keyrest - lambda {|x,**y| }.parameters.last.first.should == :keyrest + -> **x { }.parameters.first.first.should == :keyrest + -> x, **y { }.parameters.last.first.should == :keyrest proc {|**x| }.parameters.first.first.should == :keyrest proc {|x,**y| }.parameters.last.first.should == :keyrest end it "sets the first element of each sub-Array to :block for parameters prefixed with ampersands" do - lambda {|&x| }.parameters.first.first.should == :block - lambda {|x,&y| }.parameters.last.first.should == :block + -> &x { }.parameters.first.first.should == :block + -> x, &y { }.parameters.last.first.should == :block proc {|&x| }.parameters.first.first.should == :block proc {|x,&y| }.parameters.last.first.should == :block end it "sets the second element of each sub-Array to the name of the argument" do - lambda {|x| }.parameters.first.last.should == :x - lambda {|x=Math::PI| }.parameters.first.last.should == :x - lambda {|an_argument, glark, &foo| }.parameters[1].last.should == :glark - lambda {|*rest| }.parameters.first.last.should == :rest - lambda {|&block| }.parameters.first.last.should == :block + -> x { }.parameters.first.last.should == :x + -> x=Math::PI { }.parameters.first.last.should == :x + -> an_argument, glark, &foo { }.parameters[1].last.should == :glark + -> *rest { }.parameters.first.last.should == :rest + -> &block { }.parameters.first.last.should == :block proc {|x| }.parameters.first.last.should == :x proc {|x=Math::PI| }.parameters.first.last.should == :x proc {|an_argument, glark, &foo| }.parameters[1].last.should == :glark @@ -76,20 +99,85 @@ describe "Proc#parameters" do proc {|&block| }.parameters.first.last.should == :block end - it "ignores unnamed rest args" do - lambda {|x,|}.parameters.should == [[:req, :x]] + it "ignores unnamed rest arguments" do + -> x {}.parameters.should == [[:req, :x]] + end + + it "ignores implicit rest arguments" do + proc { |x, | }.parameters.should == [[:opt, :x]] + -> x { }.parameters.should == [[:req, :x]] + end + + it "adds rest arg with name * for \"star\" argument" do + -> * {}.parameters.should == [[:rest, :*]] end - it "adds nameless rest arg for \"star\" argument" do - lambda {|x,*|}.parameters.should == [[:req, :x], [:rest]] + it "adds keyrest arg with ** as a name for \"double star\" argument" do + -> ** {}.parameters.should == [[:keyrest, :**]] + end + + it "adds block arg with name & for anonymous block argument" do + -> & {}.parameters.should == [[:block, :&]] end it "does not add locals as block options with a block and splat" do - lambda do |*args, &blk| + -> *args, &blk do local_is_not_parameter = {} end.parameters.should == [[:rest, :args], [:block, :blk]] proc do |*args, &blk| local_is_not_parameter = {} end.parameters.should == [[:rest, :args], [:block, :blk]] end + + it "returns all parameters defined with the name _ as _" do + proc = proc {|_, _, _ = 1, *_, _:, _: 2, **_, &_| } + proc.parameters.should == [ + [:opt, :_], + [:opt, :_], + [:opt, :_], + [:rest, :_], + [:keyreq, :_], + [:key, :_], + [:keyrest, :_], + [:block, :_] + ] + + lambda = -> _, _, _ = 1, *_, _:, _: 2, **_, &_ {} + lambda.parameters.should == [ + [:req, :_], + [:req, :_], + [:opt, :_], + [:rest, :_], + [:keyreq, :_], + [:key, :_], + [:keyrest, :_], + [:block, :_] + ] + end + + it "returns :nokey for **nil parameter" do + proc { |**nil| }.parameters.should == [[:nokey]] + end + + ruby_version_is "3.4"..."4.0" do + it "handles the usage of `it` as a parameter" do + eval("proc { it }").parameters.should == [[:opt, nil]] + eval("lambda { it }").parameters.should == [[:req]] + end + end + + ruby_version_is "4.0" do + it "handles the usage of `it` as a parameter" do + eval("proc { it }").parameters.should == [[:opt]] + eval("lambda { it }").parameters.should == [[:req]] + end + end + + ruby_version_is "4.1" do + it "returns :noblock for &nil parameter" do + eval <<~RUBY + proc { |&nil| }.parameters.should == [[:noblock]] + RUBY + end + end end diff --git a/spec/ruby/core/proc/ruby2_keywords_spec.rb b/spec/ruby/core/proc/ruby2_keywords_spec.rb new file mode 100644 index 0000000000..e06fad8693 --- /dev/null +++ b/spec/ruby/core/proc/ruby2_keywords_spec.rb @@ -0,0 +1,66 @@ +require_relative '../../spec_helper' + +describe "Proc#ruby2_keywords" do + it "marks the final hash argument as keyword hash" do + f = -> *a { a.last } + f.ruby2_keywords + + last = f.call(1, 2, a: "a") + Hash.ruby2_keywords_hash?(last).should == true + end + + it "applies to the underlying method and applies across duplication" do + f1 = -> *a { a.last } + f1.ruby2_keywords + f2 = f1.dup + + Hash.ruby2_keywords_hash?(f1.call(1, 2, a: "a")).should == true + Hash.ruby2_keywords_hash?(f2.call(1, 2, a: "a")).should == true + + f3 = -> *a { a.last } + f4 = f3.dup + f3.ruby2_keywords + + Hash.ruby2_keywords_hash?(f3.call(1, 2, a: "a")).should == true + Hash.ruby2_keywords_hash?(f4.call(1, 2, a: "a")).should == true + end + + it "returns self" do + f = -> *a { } + f.ruby2_keywords.should.equal? f + end + + it "prints warning when a proc does not accept argument splat" do + f = -> a, b, c { } + + -> { + f.ruby2_keywords + }.should complain(/Skipping set of ruby2_keywords flag for/) + end + + it "prints warning when a proc accepts keywords" do + f = -> *a, b: { } + + -> { + f.ruby2_keywords + }.should complain(/Skipping set of ruby2_keywords flag for/) + end + + it "prints warning when a proc accepts keyword splat" do + f = -> *a, **b { } + + -> { + f.ruby2_keywords + }.should complain(/Skipping set of ruby2_keywords flag for/) + end + + ruby_version_is "4.0" do + it "prints warning when a proc accepts post arguments" do + f = -> *a, b { } + + -> { + f.ruby2_keywords + }.should complain(/Skipping set of ruby2_keywords flag for/) + end + end +end diff --git a/spec/ruby/core/proc/shared/call.rb b/spec/ruby/core/proc/shared/call.rb index 996d0e055d..fae2331b68 100644 --- a/spec/ruby/core/proc/shared/call.rb +++ b/spec/ruby/core/proc/shared/call.rb @@ -3,7 +3,7 @@ require_relative '../fixtures/common' describe :proc_call, shared: true do it "invokes self" do Proc.new { "test!" }.send(@method).should == "test!" - lambda { "test!" }.send(@method).should == "test!" + -> { "test!" }.send(@method).should == "test!" proc { "test!" }.send(@method).should == "test!" end @@ -12,9 +12,9 @@ describe :proc_call, shared: true do Proc.new { |*args| args }.send(@method, 1, 2, 3, 4).should == [1, 2, 3, 4] Proc.new { |_, *args| args }.send(@method, 1, 2, 3).should == [2, 3] - lambda { |a, b| a + b }.send(@method, 1, 2).should == 3 - lambda { |*args| args }.send(@method, 1, 2, 3, 4).should == [1, 2, 3, 4] - lambda { |_, *args| args }.send(@method, 1, 2, 3).should == [2, 3] + -> a, b { a + b }.send(@method, 1, 2).should == 3 + -> *args { args }.send(@method, 1, 2, 3, 4).should == [1, 2, 3, 4] + -> _, *args { args }.send(@method, 1, 2, 3).should == [2, 3] proc { |a, b| a + b }.send(@method, 1, 2).should == 3 proc { |*args| args }.send(@method, 1, 2, 3, 4).should == [1, 2, 3, 4] @@ -49,6 +49,9 @@ describe :proc_call_on_proc_or_lambda, shared: true do a = proc {|x| x}.send(@method, 1, 2, 3) a.should == 1 + + a = proc {|x:| x}.send(@method, 2, x: 1) + a.should == 1 end it "will call #to_ary on argument and return self if return is nil" do @@ -65,28 +68,28 @@ describe :proc_call_on_proc_or_lambda, shared: true do end it "raises an ArgumentError on excess arguments when self is a lambda" do - lambda { - lambda {|x| x}.send(@method, 1, 2) - }.should raise_error(ArgumentError) + -> { + -> x { x }.send(@method, 1, 2) + }.should.raise(ArgumentError) - lambda { - lambda {|x| x}.send(@method, 1, 2, 3) - }.should raise_error(ArgumentError) + -> { + -> x { x }.send(@method, 1, 2, 3) + }.should.raise(ArgumentError) end it "raises an ArgumentError on missing arguments when self is a lambda" do - lambda { - lambda {|x| x}.send(@method) - }.should raise_error(ArgumentError) + -> { + -> x { x }.send(@method) + }.should.raise(ArgumentError) - lambda { - lambda {|x,y| [x,y]}.send(@method, 1) - }.should raise_error(ArgumentError) + -> { + -> x, y { [x,y] }.send(@method, 1) + }.should.raise(ArgumentError) end it "treats a single Array argument as a single argument when self is a lambda" do - lambda { |a| a }.send(@method, [1, 2]).should == [1, 2] - lambda { |a, b| [a, b] }.send(@method, [1, 2], 3).should == [[1,2], 3] + -> a { a }.send(@method, [1, 2]).should == [1, 2] + -> a, b { [a, b] }.send(@method, [1, 2], 3).should == [[1,2], 3] end it "treats a single Array argument as a single argument when self is a proc" do diff --git a/spec/ruby/core/proc/shared/call_arguments.rb b/spec/ruby/core/proc/shared/call_arguments.rb index 2e510b194e..91ada3439e 100644 --- a/spec/ruby/core/proc/shared/call_arguments.rb +++ b/spec/ruby/core/proc/shared/call_arguments.rb @@ -1,7 +1,29 @@ describe :proc_call_block_args, shared: true do it "can receive block arguments" do Proc.new {|&b| b.send(@method)}.send(@method) {1 + 1}.should == 2 - lambda {|&b| b.send(@method)}.send(@method) {1 + 1}.should == 2 + -> &b { b.send(@method)}.send(@method) {1 + 1}.should == 2 proc {|&b| b.send(@method)}.send(@method) {1 + 1}.should == 2 end + + it "yields to the block given at declaration and not to the block argument" do + proc_creator = Object.new + def proc_creator.create + Proc.new do |&b| + yield + end + end + a_proc = proc_creator.create { 7 } + a_proc.send(@method) { 3 }.should == 7 + end + + it "can call its block argument declared with a block argument" do + proc_creator = Object.new + def proc_creator.create(method_name) + Proc.new do |&b| + yield + b.send(method_name) + end + end + a_proc = proc_creator.create(@method) { 7 } + a_proc.call { 3 }.should == 10 + end end diff --git a/spec/ruby/core/proc/shared/compose.rb b/spec/ruby/core/proc/shared/compose.rb index 64338cada8..c004cec7c9 100644 --- a/spec/ruby/core/proc/shared/compose.rb +++ b/spec/ruby/core/proc/shared/compose.rb @@ -1,47 +1,22 @@ describe :proc_compose, shared: true do - ruby_version_is "2.6"..."2.7" do - it "raises NoMethodError when called if passed not callable object" do - not_callable = Object.new - composed = @object.call.send(@method, not_callable) + it "raises TypeError if passed not callable object" do + lhs = @object.call + not_callable = Object.new - -> { - composed.call('a') - }.should raise_error(NoMethodError, /undefined method `call' for/) + -> { + lhs.send(@method, not_callable) + }.should.raise(TypeError, "callable object is expected") - end - - it "when called does not try to coerce argument with #to_proc" do - succ = Object.new - def succ.to_proc(s); s.succ; end - - composed = @object.call.send(@method, succ) - - -> { - composed.call('a') - }.should raise_error(NoMethodError, /undefined method `call' for/) - end end - ruby_version_is "2.7" do # https://bugs.ruby-lang.org/issues/15428 - it "raises TypeError if passed not callable object" do - lhs = @object.call - not_callable = Object.new - - -> { - lhs.send(@method, not_callable) - }.should raise_error(TypeError, "callable object is expected") - - end - - it "does not try to coerce argument with #to_proc" do - lhs = @object.call + it "does not try to coerce argument with #to_proc" do + lhs = @object.call - succ = Object.new - def succ.to_proc(s); s.succ; end + succ = Object.new + def succ.to_proc(s); s.succ; end - -> { - lhs.send(@method, succ) - }.should raise_error(TypeError, "callable object is expected") - end + -> { + lhs.send(@method, succ) + }.should.raise(TypeError, "callable object is expected") end end diff --git a/spec/ruby/core/proc/shared/dup.rb b/spec/ruby/core/proc/shared/dup.rb index fb6fff299d..2821d2e00f 100644 --- a/spec/ruby/core/proc/shared/dup.rb +++ b/spec/ruby/core/proc/shared/dup.rb @@ -1,10 +1,39 @@ describe :proc_dup, shared: true do it "returns a copy of self" do - a = lambda { "hello" } + a = -> { "hello" } b = a.send(@method) - a.should_not equal(b) + a.should_not.equal?(b) a.call.should == b.call end + + it "returns an instance of subclass" do + cl = Class.new(Proc) + + cl.new{}.send(@method).class.should == cl + end + + ruby_version_is "3.4" do + it "copies instance variables" do + proc = -> { "hello" } + proc.instance_variable_set(:@ivar, 1) + cl = proc.send(@method) + cl.instance_variables.should == [:@ivar] + end + + it "copies the finalizer" do + code = <<-'RUBY' + obj = Proc.new { } + + ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" }) + + obj.clone + + exit 0 + RUBY + + ruby_exe(code).lines.sort.should == ["finalized\n", "finalized\n"] + end + end end diff --git a/spec/ruby/core/proc/shared/equal.rb b/spec/ruby/core/proc/shared/equal.rb index a5d067cea3..4f6f6c41be 100644 --- a/spec/ruby/core/proc/shared/equal.rb +++ b/spec/ruby/core/proc/shared/equal.rb @@ -3,29 +3,29 @@ require_relative '../fixtures/common' describe :proc_equal, shared: true do it "is a public method" do - Proc.should have_public_instance_method(@method, false) + Proc.public_instance_methods(false).should.include?(@method) end it "returns true if self and other are the same object" do p = proc { :foo } - p.send(@method, p).should be_true + p.send(@method, p).should == true p = Proc.new { :foo } - p.send(@method, p).should be_true + p.send(@method, p).should == true - p = lambda { :foo } - p.send(@method, p).should be_true + p = -> { :foo } + p.send(@method, p).should == true end it "returns true if other is a dup of the original" do p = proc { :foo } - p.send(@method, p.dup).should be_true + p.send(@method, p.dup).should == true p = Proc.new { :foo } - p.send(@method, p.dup).should be_true + p.send(@method, p.dup).should == true - p = lambda { :foo } - p.send(@method, p.dup).should be_true + p = -> { :foo } + p.send(@method, p.dup).should == true end # identical here means the same method invocation. @@ -33,68 +33,51 @@ describe :proc_equal, shared: true do a = ProcSpecs.proc_for_1 b = ProcSpecs.proc_for_1 - a.send(@method, b).should be_false + a.send(@method, b).should == false end - it "returns true if both procs have the same body and environment" do + it "returns false if procs are distinct but have the same body and environment" do p = proc { :foo } p2 = proc { :foo } - p.send(@method, p2).should be_true + p.send(@method, p2).should == false end - it "returns true if both lambdas with the same body and environment" do - x = lambda { :foo } - x2 = lambda { :foo } - x.send(@method, x2).should be_true + it "returns false if lambdas are distinct but have same body and environment" do + x = -> { :foo } + x2 = -> { :foo } + x.send(@method, x2).should == false end - it "returns true if both different kinds of procs with the same body and env" do - p = lambda { :foo } + it "returns false if using comparing lambda to proc, even with the same body and env" do + p = -> { :foo } p2 = proc { :foo } - p.send(@method, p2).should be_true + p.send(@method, p2).should == false x = proc { :bar } - x2 = lambda { :bar } - x.send(@method, x2).should be_true + x2 = -> { :bar } + x.send(@method, x2).should == false end it "returns false if other is not a Proc" do p = proc { :foo } - p.send(@method, []).should be_false + p.send(@method, []).should == false p = Proc.new { :foo } - p.send(@method, Object.new).should be_false + p.send(@method, Object.new).should == false - p = lambda { :foo } - p.send(@method, :foo).should be_false + p = -> { :foo } + p.send(@method, :foo).should == false end it "returns false if self and other are both procs but have different bodies" do p = proc { :bar } p2 = proc { :foo } - p.send(@method, p2).should be_false + p.send(@method, p2).should == false end it "returns false if self and other are both lambdas but have different bodies" do - p = lambda { :foo } - p2 = lambda { :bar } - p.send(@method, p2).should be_false - end -end - -describe :proc_equal_undefined, shared: true do - it "is not defined" do - Proc.should_not have_instance_method(@method, false) - end - - it "returns false if other is a dup of the original" do - p = proc { :foo } - p.send(@method, p.dup).should be_false - - p = Proc.new { :foo } - p.send(@method, p.dup).should be_false - - p = lambda { :foo } - p.send(@method, p.dup).should be_false + p = -> { :foo } + p2 = -> { :bar } + p.send(@method, p2).should == false end end diff --git a/spec/ruby/core/proc/shared/to_s.rb b/spec/ruby/core/proc/shared/to_s.rb index 46b21dd083..a52688a89f 100644 --- a/spec/ruby/core/proc/shared/to_s.rb +++ b/spec/ruby/core/proc/shared/to_s.rb @@ -1,55 +1,60 @@ describe :proc_to_s, shared: true do describe "for a proc created with Proc.new" do - it "returns a description optionally including file and line number" do - Proc.new { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?)(@([^ ]*)\/to_s\.rb:4)?>$/ + it "returns a description including file and line number" do + Proc.new { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?) #{Regexp.escape __FILE__}:#{__LINE__ }>$/ end - it "has an ASCII-8BIT encoding" do - Proc.new { "hello" }.send(@method).encoding.should == Encoding::ASCII_8BIT + it "has a binary encoding" do + Proc.new { "hello" }.send(@method).encoding.should == Encoding::BINARY end end describe "for a proc created with lambda" do - it "returns a description including '(lambda)' and optionally including file and line number" do - lambda { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?)(@([^ ]*)\/to_s\.rb:10)? \(lambda\)>$/ + it "returns a description including '(lambda)' and including file and line number" do + -> { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?) #{Regexp.escape __FILE__}:#{__LINE__ } \(lambda\)>$/ end - it "has an ASCII-8BIT encoding" do - lambda { "hello" }.send(@method).encoding.should == Encoding::ASCII_8BIT + it "has a binary encoding" do + -> { "hello" }.send(@method).encoding.should == Encoding::BINARY end end describe "for a proc created with proc" do - it "returns a description optionally including file and line number" do - proc { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?)(@([^ ]*)\/to_s\.rb:16)?>$/ + it "returns a description including file and line number" do + proc { "hello" }.send(@method).should =~ /^#<Proc:([^ ]*?) #{Regexp.escape __FILE__}:#{__LINE__ }>$/ end - it "has an ASCII-8BIT encoding" do - proc { "hello" }.send(@method).encoding.should == Encoding::ASCII_8BIT + it "has a binary encoding" do + proc { "hello" }.send(@method).encoding.should == Encoding::BINARY end end describe "for a proc created with UnboundMethod#to_proc" do it "returns a description including '(lambda)' and optionally including file and line number" do def hello; end - method("hello").to_proc.send(@method).should =~ /^#<Proc:([^ ]*?)(@([^ ]*)\/to_s\.rb:22)? \(lambda\)>$/ + s = method("hello").to_proc.send(@method) + if s.include? __FILE__ + s.should =~ /^#<Proc:([^ ]*?) #{Regexp.escape __FILE__}:#{__LINE__ - 3} \(lambda\)>$/ + else + s.should =~ /^#<Proc:([^ ]*?) \(lambda\)>$/ + end end - it "has an ASCII-8BIT encoding" do + it "has a binary encoding" do def hello; end - method("hello").to_proc.send(@method).encoding.should == Encoding::ASCII_8BIT + method("hello").to_proc.send(@method).encoding.should == Encoding::BINARY end end describe "for a proc created with Symbol#to_proc" do it "returns a description including '(&:symbol)'" do proc = :foobar.to_proc - proc.send(@method).should =~ /^#<Proc:0x\h+\(&:foobar\)>$/ + proc.send(@method).should.include?('(&:foobar)') end - it "has an ASCII-8BIT encoding" do + it "has a binary encoding" do proc = :foobar.to_proc - proc.send(@method).encoding.should == Encoding::ASCII_8BIT + proc.send(@method).encoding.should == Encoding::BINARY end end end diff --git a/spec/ruby/core/proc/source_location_spec.rb b/spec/ruby/core/proc/source_location_spec.rb index 89409c357b..d27ad0559e 100644 --- a/spec/ruby/core/proc/source_location_spec.rb +++ b/spec/ruby/core/proc/source_location_spec.rb @@ -10,52 +10,52 @@ describe "Proc#source_location" do end it "returns an Array" do - @proc.source_location.should be_an_instance_of(Array) - @proc_new.source_location.should be_an_instance_of(Array) - @lambda.source_location.should be_an_instance_of(Array) - @method.source_location.should be_an_instance_of(Array) + @proc.source_location.should.instance_of?(Array) + @proc_new.source_location.should.instance_of?(Array) + @lambda.source_location.should.instance_of?(Array) + @method.source_location.should.instance_of?(Array) end it "sets the first value to the path of the file in which the proc was defined" do file = @proc.source_location.first - file.should be_an_instance_of(String) - file.should == File.realpath('../fixtures/source_location.rb', __FILE__) + file.should.instance_of?(String) + file.should == File.realpath('fixtures/source_location.rb', __dir__) file = @proc_new.source_location.first - file.should be_an_instance_of(String) - file.should == File.realpath('../fixtures/source_location.rb', __FILE__) + file.should.instance_of?(String) + file.should == File.realpath('fixtures/source_location.rb', __dir__) file = @lambda.source_location.first - file.should be_an_instance_of(String) - file.should == File.realpath('../fixtures/source_location.rb', __FILE__) + file.should.instance_of?(String) + file.should == File.realpath('fixtures/source_location.rb', __dir__) file = @method.source_location.first - file.should be_an_instance_of(String) - file.should == File.realpath('../fixtures/source_location.rb', __FILE__) + file.should.instance_of?(String) + file.should == File.realpath('fixtures/source_location.rb', __dir__) end - it "sets the last value to a Fixnum representing the line on which the proc was defined" do + it "sets the last value to an Integer representing the line on which the proc was defined" do line = @proc.source_location.last - line.should be_an_instance_of(Fixnum) + line.should.instance_of?(Integer) line.should == 4 line = @proc_new.source_location.last - line.should be_an_instance_of(Fixnum) + line.should.instance_of?(Integer) line.should == 12 line = @lambda.source_location.last - line.should be_an_instance_of(Fixnum) + line.should.instance_of?(Integer) line.should == 8 line = @method.source_location.last - line.should be_an_instance_of(Fixnum) + line.should.instance_of?(Integer) line.should == 15 end it "works even if the proc was created on the same line" do proc { true }.source_location.should == [__FILE__, __LINE__] Proc.new { true }.source_location.should == [__FILE__, __LINE__] - lambda { true }.source_location.should == [__FILE__, __LINE__] + -> { true }.source_location.should == [__FILE__, __LINE__] end it "returns the first line of a multi-line proc (i.e. the line containing 'proc do')" do @@ -83,4 +83,9 @@ describe "Proc#source_location" do proc.source_location.should == nil end + + it "works for eval with a given line" do + proc = eval('-> {}', nil, "foo", 100) + proc.source_location.should == ["foo", 100] + end end diff --git a/spec/ruby/core/proc/to_proc_spec.rb b/spec/ruby/core/proc/to_proc_spec.rb index 24e66760e4..7f35a4f19b 100644 --- a/spec/ruby/core/proc/to_proc_spec.rb +++ b/spec/ruby/core/proc/to_proc_spec.rb @@ -2,8 +2,8 @@ require_relative '../../spec_helper' describe "Proc#to_proc" do it "returns self" do - [Proc.new {}, lambda {}, proc {}].each { |p| - p.to_proc.should equal(p) + [Proc.new {}, -> {}, proc {}].each { |p| + p.to_proc.should.equal?(p) } end end |
