summaryrefslogtreecommitdiff
path: root/spec/ruby/core/proc
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core/proc')
-rw-r--r--spec/ruby/core/proc/allocate_spec.rb4
-rw-r--r--spec/ruby/core/proc/arity_spec.rb18
-rw-r--r--spec/ruby/core/proc/binding_spec.rb6
-rw-r--r--spec/ruby/core/proc/block_pass_spec.rb26
-rw-r--r--spec/ruby/core/proc/call_spec.rb6
-rw-r--r--spec/ruby/core/proc/case_compare_spec.rb6
-rw-r--r--spec/ruby/core/proc/clone_spec.rb30
-rw-r--r--spec/ruby/core/proc/compose_spec.rb142
-rw-r--r--spec/ruby/core/proc/curry_spec.rb65
-rw-r--r--spec/ruby/core/proc/dup_spec.rb28
-rw-r--r--spec/ruby/core/proc/element_reference_spec.rb17
-rw-r--r--spec/ruby/core/proc/eql_spec.rb6
-rw-r--r--spec/ruby/core/proc/equal_value_spec.rb6
-rw-r--r--spec/ruby/core/proc/fixtures/common.rb23
-rw-r--r--spec/ruby/core/proc/fixtures/proc_aref.rb10
-rw-r--r--spec/ruby/core/proc/fixtures/proc_aref_frozen.rb10
-rw-r--r--spec/ruby/core/proc/fixtures/source_location.rb8
-rw-r--r--spec/ruby/core/proc/hash_spec.rb6
-rw-r--r--spec/ruby/core/proc/inspect_spec.rb4
-rw-r--r--spec/ruby/core/proc/lambda_spec.rb24
-rw-r--r--spec/ruby/core/proc/new_spec.rb32
-rw-r--r--spec/ruby/core/proc/parameters_spec.rb124
-rw-r--r--spec/ruby/core/proc/ruby2_keywords_spec.rb66
-rw-r--r--spec/ruby/core/proc/shared/call.rb33
-rw-r--r--spec/ruby/core/proc/shared/call_arguments.rb24
-rw-r--r--spec/ruby/core/proc/shared/compose.rb22
-rw-r--r--spec/ruby/core/proc/shared/dup.rb31
-rw-r--r--spec/ruby/core/proc/shared/equal.rb53
-rw-r--r--spec/ruby/core/proc/shared/to_s.rb47
-rw-r--r--spec/ruby/core/proc/source_location_spec.rb88
-rw-r--r--spec/ruby/core/proc/to_proc_spec.rb4
-rw-r--r--spec/ruby/core/proc/to_s_spec.rb4
-rw-r--r--spec/ruby/core/proc/yield_spec.rb6
33 files changed, 737 insertions, 242 deletions
diff --git a/spec/ruby/core/proc/allocate_spec.rb b/spec/ruby/core/proc/allocate_spec.rb
index 6bfb94dbc2..54e1b69df9 100644
--- a/spec/ruby/core/proc/allocate_spec.rb
+++ b/spec/ruby/core/proc/allocate_spec.rb
@@ -1,8 +1,8 @@
-require File.expand_path('../../../spec_helper', __FILE__)
+require_relative '../../spec_helper'
describe "Proc.allocate" do
it "raises a TypeError" do
- lambda {
+ -> {
Proc.allocate
}.should raise_error(TypeError)
end
diff --git a/spec/ruby/core/proc/arity_spec.rb b/spec/ruby/core/proc/arity_spec.rb
index 251710a663..5c7728cb30 100644
--- a/spec/ruby/core/proc/arity_spec.rb
+++ b/spec/ruby/core/proc/arity_spec.rb
@@ -1,4 +1,4 @@
-require File.expand_path('../../../spec_helper', __FILE__)
+require_relative '../../spec_helper'
describe "Proc#arity" do
SpecEvaluate.desc = "for definition"
@@ -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 05cc68217e..86ab6bd400 100644
--- a/spec/ruby/core/proc/binding_spec.rb
+++ b/spec/ruby/core/proc/binding_spec.rb
@@ -1,8 +1,8 @@
-require File.expand_path('../../../spec_helper', __FILE__)
+require_relative '../../spec_helper'
describe "Proc#binding" do
it "returns a Binding instance" do
- [Proc.new{}, lambda {}, proc {}].each { |p|
+ [Proc.new{}, -> {}, proc {}].each { |p|
p.binding.should be_kind_of(Binding)
}
end
@@ -10,7 +10,7 @@ describe "Proc#binding" do
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 e956885654..411c0bf3db 100644
--- a/spec/ruby/core/proc/block_pass_spec.rb
+++ b/spec/ruby/core/proc/block_pass_spec.rb
@@ -1,4 +1,4 @@
-require File.expand_path('../../../spec_helper', __FILE__)
+require_relative '../../spec_helper'
describe "Proc as a block pass argument" do
def revivify(&b)
@@ -8,34 +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.object_id.should == p2.object_id
+ 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.object_id.should == p2.object_id
- p.should == p2
- end
-end
-
-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.object_id.should == p2.object_id
- p.should == p2
- end
-
- it "remains the same object if reconstructed with Proc.new" do
- p = Proc.new {}
- p2 = Proc.new(&p)
- p.object_id.should == p2.object_id
+ p.should equal p2
p.should == p2
end
end
diff --git a/spec/ruby/core/proc/call_spec.rb b/spec/ruby/core/proc/call_spec.rb
index 1c28eae9b0..6ec2fc8682 100644
--- a/spec/ruby/core/proc/call_spec.rb
+++ b/spec/ruby/core/proc/call_spec.rb
@@ -1,6 +1,6 @@
-require File.expand_path('../../../spec_helper', __FILE__)
-require File.expand_path('../shared/call', __FILE__)
-require File.expand_path('../shared/call_arguments', __FILE__)
+require_relative '../../spec_helper'
+require_relative 'shared/call'
+require_relative 'shared/call_arguments'
describe "Proc#call" do
it_behaves_like :proc_call, :call
diff --git a/spec/ruby/core/proc/case_compare_spec.rb b/spec/ruby/core/proc/case_compare_spec.rb
index 55760c4ff3..f11513cdb9 100644
--- a/spec/ruby/core/proc/case_compare_spec.rb
+++ b/spec/ruby/core/proc/case_compare_spec.rb
@@ -1,6 +1,6 @@
-require File.expand_path('../../../spec_helper', __FILE__)
-require File.expand_path('../shared/call', __FILE__)
-require File.expand_path('../shared/call_arguments', __FILE__)
+require_relative '../../spec_helper'
+require_relative 'shared/call'
+require_relative 'shared/call_arguments'
describe "Proc#===" do
it_behaves_like :proc_call, :===
diff --git a/spec/ruby/core/proc/clone_spec.rb b/spec/ruby/core/proc/clone_spec.rb
index 0f0806645b..730dc421a8 100644
--- a/spec/ruby/core/proc/clone_spec.rb
+++ b/spec/ruby/core/proc/clone_spec.rb
@@ -1,6 +1,30 @@
-require File.expand_path('../../../spec_helper', __FILE__)
-require File.expand_path('../shared/dup', __FILE__)
+require_relative '../../spec_helper'
+require_relative 'fixtures/common'
+require_relative 'shared/dup'
describe "Proc#clone" do
- it_behaves_like(:proc_dup, :clone)
+ it_behaves_like :proc_dup, :clone
+
+ ruby_bug "cloning a frozen proc is broken on Ruby 3.3", "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
+
+ ruby_version_is "3.3" do
+ 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
end
diff --git a/spec/ruby/core/proc/compose_spec.rb b/spec/ruby/core/proc/compose_spec.rb
new file mode 100644
index 0000000000..9e9b57e06f
--- /dev/null
+++ b/spec/ruby/core/proc/compose_spec.rb
@@ -0,0 +1,142 @@
+require_relative '../../spec_helper'
+require_relative 'shared/compose'
+
+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
+
+ 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_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).is_a?(Proc).should == true
+ (f << g).should_not.lambda?
+ end
+
+ 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?
+
+ # lambda << lambda
+ (f << lambda_proc).is_a?(Proc).should == true
+ (f << lambda_proc).should.lambda?
+
+ # proc << lambda
+ (g << f).is_a?(Proc).should == true
+ (g << f).should.lambda?
+ end
+
+ it "may accept multiple arguments" do
+ inc = proc { |n| n + 1 }
+ mul = proc { |n, m| n * m }
+
+ (inc << mul).call(2, 3).should == 7
+ 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
+
+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
+
+ 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 == 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_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).is_a?(Proc).should == true
+ (f >> g).should_not.lambda?
+ end
+
+ it "is a Proc when other is lambda" do
+ f = proc { |x| x * x }
+ g = -> x { x + x }
+
+ (f >> g).is_a?(Proc).should == true
+ (f >> g).should_not.lambda?
+ end
+
+ it "is a lambda when self is lambda" do
+ f = -> x { x * x }
+ g = proc { |x| x + x }
+
+ (f >> g).is_a?(Proc).should == true
+ (f >> g).should.lambda?
+ end
+
+ 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
+
+ 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 a294606957..6daabe0ee1 100644
--- a/spec/ruby/core/proc/curry_spec.rb
+++ b/spec/ruby/core/proc/curry_spec.rb
@@ -1,9 +1,9 @@
-require File.expand_path('../../../spec_helper', __FILE__)
+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
@@ -12,7 +12,7 @@ describe "Proc#curry" do
end
it "returns a Proc when called on a lambda" do
- p = lambda { true }
+ p = -> { true }
p.curry.should be_an_instance_of(Proc)
end
@@ -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_error
@lambda_add.curry
- lambda { @lambda_add.curry }.should_not raise_error
+ -> { @lambda_add.curry }.should_not raise_error
end
it "can be passed superfluous arguments if created from a proc" do
@@ -49,19 +49,19 @@ 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_error(ArgumentError)
+ -> { @lambda_add.curry[1,2].curry[3,4,5,6] }.should raise_error(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
@@ -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,13 +93,13 @@ 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_error
+ -> { @lambda_add.curry(3) }.should_not raise_error
end
it "returns a Proc when called on a proc" do
@@ -117,22 +117,22 @@ describe "Proc#curry with arity argument" do
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_error(ArgumentError)
+ -> { -> x, y, z, *more{}.curry(2) }.should raise_error(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 be_an_instance_of(Proc)
+ -> a, b, c, d=nil, *e {}.curry(4).should be_an_instance_of(Proc)
+ -> a, b, c, *d {}.curry(4).should be_an_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_error(ArgumentError)
+ -> { -> { true }.curry(1) }.should raise_error(ArgumentError)
+ -> { -> a, b=nil {}.curry(5) }.should raise_error(ArgumentError)
+ -> { -> a, &b {}.curry(2) }.should raise_error(ArgumentError)
+ -> { -> a, b=nil, &c {}.curry(3) }.should raise_error(ArgumentError)
end
it "calls the curried proc with the arguments if _arity_ arguments have been given" do
@@ -152,29 +152,28 @@ describe "Proc#curry with arity argument" do
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_error
@lambda_add.curry(3)
- lambda { @lambda_add.curry(3) }.should_not raise_error
+ -> { @lambda_add.curry(3) }.should_not raise_error
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_error(ArgumentError)
+ -> { @lambda_add.curry(3)[1,2].curry(3)[3,4,5,6] }.should raise_error(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 ea3fe8aac9..716357d1f0 100644
--- a/spec/ruby/core/proc/dup_spec.rb
+++ b/spec/ruby/core/proc/dup_spec.rb
@@ -1,6 +1,28 @@
-require File.expand_path('../../../spec_helper', __FILE__)
-require File.expand_path('../shared/dup', __FILE__)
+require_relative '../../spec_helper'
+require_relative 'fixtures/common'
+require_relative 'shared/dup'
describe "Proc#dup" do
- it_behaves_like(:proc_dup, :dup)
+ 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
+
+ ruby_version_is "3.3" do
+ 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
end
diff --git a/spec/ruby/core/proc/element_reference_spec.rb b/spec/ruby/core/proc/element_reference_spec.rb
index f3dec21253..81ceb91af5 100644
--- a/spec/ruby/core/proc/element_reference_spec.rb
+++ b/spec/ruby/core/proc/element_reference_spec.rb
@@ -1,6 +1,8 @@
-require File.expand_path('../../../spec_helper', __FILE__)
-require File.expand_path('../shared/call', __FILE__)
-require File.expand_path('../shared/call_arguments', __FILE__)
+require_relative '../../spec_helper'
+require_relative 'shared/call'
+require_relative 'shared/call_arguments'
+require_relative 'fixtures/proc_aref'
+require_relative 'fixtures/proc_aref_frozen'
describe "Proc#[]" do
it_behaves_like :proc_call, :[]
@@ -14,3 +16,12 @@ end
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
+
+describe "Proc#[] with frozen_string_literal: true/false" 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
+end
diff --git a/spec/ruby/core/proc/eql_spec.rb b/spec/ruby/core/proc/eql_spec.rb
index e0cc80bb48..ad8f6749fc 100644
--- a/spec/ruby/core/proc/eql_spec.rb
+++ b/spec/ruby/core/proc/eql_spec.rb
@@ -1,6 +1,6 @@
-require File.expand_path('../../../spec_helper', __FILE__)
-require File.expand_path('../shared/equal', __FILE__)
+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 e50ea1a53b..ec7f274732 100644
--- a/spec/ruby/core/proc/equal_value_spec.rb
+++ b/spec/ruby/core/proc/equal_value_spec.rb
@@ -1,6 +1,6 @@
-require File.expand_path('../../../spec_helper', __FILE__)
-require File.expand_path('../shared/equal', __FILE__)
+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
new file mode 100644
index 0000000000..8ee355b14c
--- /dev/null
+++ b/spec/ruby/core/proc/fixtures/proc_aref.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: false
+module ProcArefSpecs
+ def self.aref
+ proc {|a| a }["sometext"]
+ end
+
+ def self.aref_freeze
+ proc {|a| a }["sometext".freeze]
+ end
+end
diff --git a/spec/ruby/core/proc/fixtures/proc_aref_frozen.rb b/spec/ruby/core/proc/fixtures/proc_aref_frozen.rb
new file mode 100644
index 0000000000..50a330ba4f
--- /dev/null
+++ b/spec/ruby/core/proc/fixtures/proc_aref_frozen.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+module ProcArefFrozenSpecs
+ def self.aref
+ proc {|a| a }["sometext"]
+ end
+
+ def self.aref_freeze
+ proc {|a| a }["sometext".freeze]
+ end
+end
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 1f5b6d5aa1..ebe0fde1a0 100644
--- a/spec/ruby/core/proc/hash_spec.rb
+++ b/spec/ruby/core/proc/hash_spec.rb
@@ -1,13 +1,13 @@
-require File.expand_path('../../../spec_helper', __FILE__)
+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
+ -> {}.respond_to?(:hash).should be_true
end
it "returns an Integer" do
- proc { 1 + 489 }.hash.should be_kind_of(Fixnum)
+ proc { 1 + 489 }.hash.should be_kind_of(Integer)
end
it "is stable" do
diff --git a/spec/ruby/core/proc/inspect_spec.rb b/spec/ruby/core/proc/inspect_spec.rb
index 860647baa7..f53d34116f 100644
--- a/spec/ruby/core/proc/inspect_spec.rb
+++ b/spec/ruby/core/proc/inspect_spec.rb
@@ -1,5 +1,5 @@
-require File.expand_path('../../../spec_helper', __FILE__)
-require File.expand_path('../shared/to_s', __FILE__)
+require_relative '../../spec_helper'
+require_relative 'shared/to_s'
describe "Proc#inspect" do
it_behaves_like :proc_to_s, :inspect
diff --git a/spec/ruby/core/proc/lambda_spec.rb b/spec/ruby/core/proc/lambda_spec.rb
index 33c9ebdd55..5c3c38fc2a 100644
--- a/spec/ruby/core/proc/lambda_spec.rb
+++ b/spec/ruby/core/proc/lambda_spec.rb
@@ -1,9 +1,9 @@
-require File.expand_path('../../../spec_helper', __FILE__)
-require File.expand_path('../fixtures/common', __FILE__)
+require_relative '../../spec_helper'
+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 be_true
end
it "returns false if the Proc was created from a block with the proc keyword" do
@@ -14,18 +14,20 @@ describe "Proc#lambda?" 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
+ ruby_version_is ""..."3.3" do
+ it "is preserved when passing a Proc with & to the lambda keyword" do
+ suppress_warning {lambda(&->{})}.lambda?.should be_true
+ suppress_warning {lambda(&proc{})}.lambda?.should be_false
+ end
end
it "is preserved when passing a Proc with & to the proc keyword" do
- proc(&lambda{}).lambda?.should be_true
+ proc(&->{}).lambda?.should be_true
proc(&proc{}).lambda?.should be_false
end
it "is preserved when passing a Proc with & to Proc.new" do
- Proc.new(&lambda{}).lambda?.should be_true
+ Proc.new(&->{}).lambda?.should be_true
Proc.new(&proc{}).lambda?.should be_false
end
@@ -34,7 +36,7 @@ describe "Proc#lambda?" do
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(&->{}).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
end
@@ -47,13 +49,13 @@ describe "Proc#lambda?" do
# [ruby-core:24127]
it "is preserved when a Proc is curried" do
- lambda{}.curry.lambda?.should be_true
+ ->{}.curry.lambda?.should be_true
proc{}.curry.lambda?.should be_false
Proc.new{}.curry.lambda?.should be_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
+ -> 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
end
diff --git a/spec/ruby/core/proc/new_spec.rb b/spec/ruby/core/proc/new_spec.rb
index 5dc0061a47..b2b7387756 100644
--- a/spec/ruby/core/proc/new_spec.rb
+++ b/spec/ruby/core/proc/new_spec.rb
@@ -1,5 +1,5 @@
-require File.expand_path('../../../spec_helper', __FILE__)
-require File.expand_path('../fixtures/common', __FILE__)
+require_relative '../../spec_helper'
+require_relative 'fixtures/common'
describe "Proc.new with an associated block" do
it "returns a proc that represents the block" do
@@ -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_error(LocalJumpError)
end
it "returns from within enclosing method when 'return' is used in the block" do
@@ -94,18 +94,6 @@ describe "Proc.new with an associated block" do
obj.first.should == :a
obj.second.should == 2
end
-
- 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
describe "Proc.new with a block argument" do
@@ -167,24 +155,24 @@ end
describe "Proc.new without a block" do
it "raises an ArgumentError" do
- lambda { Proc.new }.should raise_error(ArgumentError)
+ -> { Proc.new }.should raise_error(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_error(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)
+ -> { ProcSpecs.new_proc_subclass_in_method }.should raise_error(ArgumentError)
end
- it "uses the implicit block from an enclosing method" do
+ it "raises an ArgumentError when passed no block" do
def some_method
Proc.new
end
- prc = some_method { "hello" }
-
- prc.call.should == "hello"
+ -> { ProcSpecs.new_proc_in_method { "hello" } }.should raise_error(ArgumentError, 'tried to create Proc object without a block')
+ -> { ProcSpecs.new_proc_subclass_in_method { "hello" } }.should raise_error(ArgumentError, 'tried to create Proc object without a block')
+ -> { some_method { "hello" } }.should raise_error(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 3ba8a0cc32..cf8a8f5b12 100644
--- a/spec/ruby/core/proc/parameters_spec.rb
+++ b/spec/ruby/core/proc/parameters_spec.rb
@@ -1,4 +1,4 @@
-require File.expand_path('../../../spec_helper', __FILE__)
+require_relative '../../spec_helper'
describe "Proc#parameters" do
it "returns an empty Array for a proc expecting no parameters" 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,77 @@ 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
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..d7f8f592e1
--- /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 11355537b0..dbec34df4b 100644
--- a/spec/ruby/core/proc/shared/call.rb
+++ b/spec/ruby/core/proc/shared/call.rb
@@ -1,9 +1,9 @@
-require File.expand_path('../../fixtures/common', __FILE__)
+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)
+ -> {
+ -> x { x }.send(@method, 1, 2)
}.should raise_error(ArgumentError)
- lambda {
- lambda {|x| x}.send(@method, 1, 2, 3)
+ -> {
+ -> x { x }.send(@method, 1, 2, 3)
}.should raise_error(ArgumentError)
end
it "raises an ArgumentError on missing arguments when self is a lambda" do
- lambda {
- lambda {|x| x}.send(@method)
+ -> {
+ -> x { x }.send(@method)
}.should raise_error(ArgumentError)
- lambda {
- lambda {|x,y| [x,y]}.send(@method, 1)
+ -> {
+ -> x, y { [x,y] }.send(@method, 1)
}.should raise_error(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
new file mode 100644
index 0000000000..3d3f3b310d
--- /dev/null
+++ b/spec/ruby/core/proc/shared/compose.rb
@@ -0,0 +1,22 @@
+describe :proc_compose, shared: true do
+ 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
+
+ succ = Object.new
+ def succ.to_proc(s); s.succ; end
+
+ -> {
+ lhs.send(@method, succ)
+ }.should raise_error(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..1266337f94 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.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 c2735ffb2f..d0503fb064 100644
--- a/spec/ruby/core/proc/shared/equal.rb
+++ b/spec/ruby/core/proc/shared/equal.rb
@@ -1,5 +1,5 @@
-require File.expand_path('../../../../spec_helper', __FILE__)
-require File.expand_path('../../fixtures/common', __FILE__)
+require_relative '../../../spec_helper'
+require_relative '../fixtures/common'
describe :proc_equal, shared: true do
it "is a public method" do
@@ -13,7 +13,7 @@ describe :proc_equal, shared: true do
p = Proc.new { :foo }
p.send(@method, p).should be_true
- p = lambda { :foo }
+ p = -> { :foo }
p.send(@method, p).should be_true
end
@@ -24,7 +24,7 @@ describe :proc_equal, shared: true do
p = Proc.new { :foo }
p.send(@method, p.dup).should be_true
- p = lambda { :foo }
+ p = -> { :foo }
p.send(@method, p.dup).should be_true
end
@@ -36,26 +36,26 @@ describe :proc_equal, shared: true do
a.send(@method, b).should be_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 be_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 be_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 be_false
x = proc { :bar }
- x2 = lambda { :bar }
- x.send(@method, x2).should be_true
+ x2 = -> { :bar }
+ x.send(@method, x2).should be_false
end
it "returns false if other is not a Proc" do
@@ -65,7 +65,7 @@ describe :proc_equal, shared: true do
p = Proc.new { :foo }
p.send(@method, Object.new).should be_false
- p = lambda { :foo }
+ p = -> { :foo }
p.send(@method, :foo).should be_false
end
@@ -76,25 +76,8 @@ describe :proc_equal, shared: true do
end
it "returns false if self and other are both lambdas but have different bodies" do
- p = lambda { :foo }
- p2 = lambda { :bar }
+ p = -> { :foo }
+ p2 = -> { :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
- end
-end
diff --git a/spec/ruby/core/proc/shared/to_s.rb b/spec/ruby/core/proc/shared/to_s.rb
index c3f82a73f3..a52688a89f 100644
--- a/spec/ruby/core/proc/shared/to_s.rb
+++ b/spec/ruby/core/proc/shared/to_s.rb
@@ -1,27 +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 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 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 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
+ 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 a binary encoding" do
+ def hello; end
+ 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.include?('(&:foobar)')
+ end
- method("hello").to_proc.send(@method).should =~ /^#<Proc:([^ ]*?)(@([^ ]*)\/to_s\.rb:22)? \(lambda\)>$/
+ it "has a binary encoding" do
+ proc = :foobar.to_proc
+ 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 311d13c050..fd33f21a26 100644
--- a/spec/ruby/core/proc/source_location_spec.rb
+++ b/spec/ruby/core/proc/source_location_spec.rb
@@ -1,5 +1,5 @@
-require File.expand_path('../../../spec_helper', __FILE__)
-require File.expand_path('../fixtures/source_location', __FILE__)
+require_relative '../../spec_helper'
+require_relative 'fixtures/source_location'
describe "Proc#source_location" do
before :each do
@@ -17,56 +17,88 @@ describe "Proc#source_location" do
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 = @proc.source_location[0]
file.should be_an_instance_of(String)
- file.should == File.dirname(__FILE__) + '/fixtures/source_location.rb'
+ file.should == File.realpath('fixtures/source_location.rb', __dir__)
- file = @proc_new.source_location.first
+ file = @proc_new.source_location[0]
file.should be_an_instance_of(String)
- file.should == File.dirname(__FILE__) + '/fixtures/source_location.rb'
+ file.should == File.realpath('fixtures/source_location.rb', __dir__)
- file = @lambda.source_location.first
+ file = @lambda.source_location[0]
file.should be_an_instance_of(String)
- file.should == File.dirname(__FILE__) + '/fixtures/source_location.rb'
+ file.should == File.realpath('fixtures/source_location.rb', __dir__)
- file = @method.source_location.first
+ file = @method.source_location[0]
file.should be_an_instance_of(String)
- file.should == File.dirname(__FILE__) + '/fixtures/source_location.rb'
+ 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
- line = @proc.source_location.last
- line.should be_an_instance_of(Fixnum)
+ it "sets the second value to an Integer representing the line on which the proc was defined" do
+ line = @proc.source_location[1]
+ line.should be_an_instance_of(Integer)
line.should == 4
- line = @proc_new.source_location.last
- line.should be_an_instance_of(Fixnum)
+ line = @proc_new.source_location[1]
+ line.should be_an_instance_of(Integer)
line.should == 12
- line = @lambda.source_location.last
- line.should be_an_instance_of(Fixnum)
+ line = @lambda.source_location[1]
+ line.should be_an_instance_of(Integer)
line.should == 8
- line = @method.source_location.last
- line.should be_an_instance_of(Fixnum)
+ line = @method.source_location[1]
+ line.should be_an_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__]
+ ruby_version_is(""..."4.1") do
+ proc { true }.source_location.should == [__FILE__, __LINE__]
+ Proc.new { true }.source_location.should == [__FILE__, __LINE__]
+ -> { true }.source_location.should == [__FILE__, __LINE__]
+ end
+ ruby_version_is("4.1") do
+ proc { true }.source_location.should == [__FILE__, __LINE__, 11, __LINE__, 19]
+ Proc.new { true }.source_location.should == [__FILE__, __LINE__, 15, __LINE__, 23]
+ -> { true }.source_location.should == [__FILE__, __LINE__, 6, __LINE__, 17]
+ end
end
it "returns the first line of a multi-line proc (i.e. the line containing 'proc do')" do
- ProcSpecs::SourceLocation.my_multiline_proc.source_location.last.should == 20
- ProcSpecs::SourceLocation.my_multiline_proc_new.source_location.last.should == 34
- ProcSpecs::SourceLocation.my_multiline_lambda.source_location.last.should == 27
+ ProcSpecs::SourceLocation.my_multiline_proc.source_location[1].should == 20
+ ProcSpecs::SourceLocation.my_multiline_proc_new.source_location[1].should == 34
+ ProcSpecs::SourceLocation.my_multiline_lambda.source_location[1].should == 27
end
it "returns the location of the proc's body; not necessarily the proc itself" do
- ProcSpecs::SourceLocation.my_detached_proc.source_location.last.should == 41
- ProcSpecs::SourceLocation.my_detached_proc_new.source_location.last.should == 51
- ProcSpecs::SourceLocation.my_detached_lambda.source_location.last.should == 46
+ ProcSpecs::SourceLocation.my_detached_proc.source_location[1].should == 41
+ ProcSpecs::SourceLocation.my_detached_proc_new.source_location[1].should == 51
+ ProcSpecs::SourceLocation.my_detached_lambda.source_location[1].should == 46
+ end
+
+ it "returns the same value for a proc-ified method as the method reports" do
+ method = ProcSpecs::SourceLocation.method(:my_proc)
+ proc = method.to_proc
+
+ method.source_location.should == proc.source_location
+ end
+
+ it "returns nil for a core method that has been proc-ified" do
+ method = [].method(:<<)
+ proc = method.to_proc
+
+ proc.source_location.should == nil
+ end
+
+ it "works for eval with a given line" do
+ proc = eval('-> {}', nil, "foo", 100)
+ location = proc.source_location
+ ruby_version_is(""..."4.1") do
+ location.should == ["foo", 100]
+ end
+ ruby_version_is("4.1") do
+ location.should == ["foo", 100, 0, 100, 5]
+ end
end
end
diff --git a/spec/ruby/core/proc/to_proc_spec.rb b/spec/ruby/core/proc/to_proc_spec.rb
index e5637c9f41..ffaa34929b 100644
--- a/spec/ruby/core/proc/to_proc_spec.rb
+++ b/spec/ruby/core/proc/to_proc_spec.rb
@@ -1,8 +1,8 @@
-require File.expand_path('../../../spec_helper', __FILE__)
+require_relative '../../spec_helper'
describe "Proc#to_proc" do
it "returns self" do
- [Proc.new {}, lambda {}, proc {}].each { |p|
+ [Proc.new {}, -> {}, proc {}].each { |p|
p.to_proc.should equal(p)
}
end
diff --git a/spec/ruby/core/proc/to_s_spec.rb b/spec/ruby/core/proc/to_s_spec.rb
index e0b248c369..5e9c46b6b8 100644
--- a/spec/ruby/core/proc/to_s_spec.rb
+++ b/spec/ruby/core/proc/to_s_spec.rb
@@ -1,5 +1,5 @@
-require File.expand_path('../../../spec_helper', __FILE__)
-require File.expand_path('../shared/to_s', __FILE__)
+require_relative '../../spec_helper'
+require_relative 'shared/to_s'
describe "Proc#to_s" do
it_behaves_like :proc_to_s, :to_s
diff --git a/spec/ruby/core/proc/yield_spec.rb b/spec/ruby/core/proc/yield_spec.rb
index 930e44ea78..365d5b04bd 100644
--- a/spec/ruby/core/proc/yield_spec.rb
+++ b/spec/ruby/core/proc/yield_spec.rb
@@ -1,6 +1,6 @@
-require File.expand_path('../../../spec_helper', __FILE__)
-require File.expand_path('../shared/call', __FILE__)
-require File.expand_path('../shared/call_arguments', __FILE__)
+require_relative '../../spec_helper'
+require_relative 'shared/call'
+require_relative 'shared/call_arguments'
describe "Proc#yield" do
it_behaves_like :proc_call, :yield