summaryrefslogtreecommitdiff
path: root/spec/ruby/core/kernel/eval_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core/kernel/eval_spec.rb')
-rw-r--r--spec/ruby/core/kernel/eval_spec.rb153
1 files changed, 110 insertions, 43 deletions
diff --git a/spec/ruby/core/kernel/eval_spec.rb b/spec/ruby/core/kernel/eval_spec.rb
index 5f4cd27da0..f9ca47866e 100644
--- a/spec/ruby/core/kernel/eval_spec.rb
+++ b/spec/ruby/core/kernel/eval_spec.rb
@@ -5,7 +5,7 @@ EvalSpecs::A.new.c
describe "Kernel#eval" do
it "is a private method" do
- Kernel.should have_private_instance_method(:eval)
+ Kernel.private_instance_methods(false).should.include?(:eval)
end
it "is a module function" do
@@ -76,12 +76,12 @@ describe "Kernel#eval" do
x = 1
bind = proc {}
- -> { eval("x", bind) }.should raise_error(TypeError)
+ -> { eval("x", bind) }.should.raise(TypeError)
end
it "does not make Proc locals visible to evaluated code" do
bind = proc { inner = 4 }
- -> { eval("inner", bind.binding) }.should raise_error(NameError)
+ -> { eval("inner", bind.binding) }.should.raise(NameError)
end
# REWRITE ME: This obscures the real behavior of where locals are stored
@@ -119,7 +119,7 @@ describe "Kernel#eval" do
outer_binding = binding
eval("if false; a = 1; end", outer_binding)
- eval("a", outer_binding).should be_nil
+ eval("a", outer_binding).should == nil
end
it "allows creating a new class in a binding" do
@@ -136,7 +136,7 @@ describe "Kernel#eval" do
expected = 'speccing.rb'
-> {
eval('if true', TOPLEVEL_BINDING, expected)
- }.should raise_error(SyntaxError) { |e|
+ }.should.raise(SyntaxError) { |e|
e.message.should =~ /#{expected}:1:.+/
}
end
@@ -145,7 +145,7 @@ describe "Kernel#eval" do
expected_file = 'speccing.rb'
-> {
eval('if true', TOPLEVEL_BINDING, expected_file, -100)
- }.should raise_error(SyntaxError) { |e|
+ }.should.raise(SyntaxError) { |e|
e.message.should =~ /#{expected_file}:-100:.+/
}
end
@@ -159,36 +159,87 @@ describe "Kernel#eval" do
end
end
- ruby_version_is ""..."3.3" do
- it "uses (eval) filename if none is provided" do
- eval("__FILE__").should == "(eval)"
- eval("__FILE__", binding).should == "(eval)"
- eval("__FILE__", binding, "success").should == "success"
- eval("eval '__FILE__', binding").should == "(eval)"
- eval("eval '__FILE__', binding", binding).should == "(eval)"
- eval("eval '__FILE__', binding", binding, 'success').should == '(eval)'
- eval("eval '__FILE__', binding, 'success'", binding).should == 'success'
+ context "parameter forwarding" do
+ it "allows anonymous rest parameter forwarding" do
+ object = Object.new
+ def object.foo(a, b, c)
+ [a, b, c]
+ end
+ def object.bar(*)
+ eval "foo(*)"
+ end
+
+ object.bar(1, 2, 3).should == [1, 2, 3]
end
- it 'uses (eval) for __FILE__ and 1 for __LINE__ with a binding argument' do
- eval("[__FILE__, __LINE__]", binding).should == ["(eval)", 1]
+ it "allows anonymous keyword parameters forwarding" do
+ object = Object.new
+ def object.foo(a:, b:, c:)
+ [a, b, c]
+ end
+ def object.bar(**)
+ eval "foo(**)"
+ end
+
+ object.bar(a: 1, b: 2, c: 3).should == [1, 2, 3]
end
- end
- ruby_version_is "3.3" do
- it "uses (eval at __FILE__:__LINE__) if none is provided" do
- eval("__FILE__").should == "(eval at #{__FILE__}:#{__LINE__})"
- eval("__FILE__", binding).should == "(eval at #{__FILE__}:#{__LINE__})"
- eval("__FILE__", binding, "success").should == "success"
- eval("eval '__FILE__', binding").should == "(eval at (eval at #{__FILE__}:#{__LINE__}):1)"
- eval("eval '__FILE__', binding", binding).should == "(eval at (eval at #{__FILE__}:#{__LINE__}):1)"
- eval("eval '__FILE__', binding", binding, 'success').should == "(eval at success:1)"
- eval("eval '__FILE__', binding, 'success'", binding).should == 'success'
+ it "allows anonymous block parameter forwarding" do
+ object = Object.new
+ def object.foo(&block)
+ block.call
+ end
+ def object.bar(&)
+ eval "foo(&)"
+ end
+
+ object.bar { :foobar }.should == :foobar
end
- it 'uses (eval at __FILE__:__LINE__) for __FILE__ and 1 for __LINE__ with a binding argument' do
- eval("[__FILE__, __LINE__]", binding).should == ["(eval at #{__FILE__}:#{__LINE__})", 1]
+ it "allows ... forwarding" do
+ object = Object.new
+ def object.foo(a, b:, &block)
+ [a, b, block.call]
+ end
+ def object.bar(...)
+ eval "foo(...)"
+ end
+
+ object.bar(1, b: 2) { 3 }.should == [1, 2, 3]
end
+
+ it "allows parameter forwarding to super" do
+ m = Module.new do
+ def foo(a, b:, &block)
+ [a, b, block.call]
+ end
+ end
+
+ c = Class.new do
+ include m
+
+ def foo(a, b:, &block)
+ eval "super"
+ end
+ end
+
+ object = c.new
+ object.foo(1, b: 2) { 3 }.should == [1, 2, 3]
+ end
+ end
+
+ it "uses (eval at __FILE__:__LINE__) if none is provided" do
+ eval("__FILE__").should == "(eval at #{__FILE__}:#{__LINE__})"
+ eval("__FILE__", binding).should == "(eval at #{__FILE__}:#{__LINE__})"
+ eval("__FILE__", binding, "success").should == "success"
+ eval("eval '__FILE__', binding").should == "(eval at (eval at #{__FILE__}:#{__LINE__}):1)"
+ eval("eval '__FILE__', binding", binding).should == "(eval at (eval at #{__FILE__}:#{__LINE__}):1)"
+ eval("eval '__FILE__', binding", binding, 'success').should == "(eval at success:1)"
+ eval("eval '__FILE__', binding, 'success'", binding).should == 'success'
+ end
+
+ it 'uses (eval at __FILE__:__LINE__) for __FILE__ and 1 for __LINE__ with a binding argument' do
+ eval("[__FILE__, __LINE__]", binding).should == ["(eval at #{__FILE__}:#{__LINE__})", 1]
end
# Found via Rubinius bug github:#149
it "does not alter the value of __FILE__ in the binding" do
@@ -212,14 +263,14 @@ describe "Kernel#eval" do
# See http://jira.codehaus.org/browse/JRUBY-5163
it "uses the receiver as self inside the eval" do
- eval("self").should equal(self)
- Kernel.eval("self").should equal(Kernel)
+ eval("self").should.equal?(self)
+ Kernel.eval("self").should.equal?(Kernel)
end
it "does not pass the block to the method being eval'ed" do
-> {
eval('KernelSpecs::EvalTest.call_yield') { "content" }
- }.should raise_error(LocalJumpError)
+ }.should.raise(LocalJumpError)
end
it "returns from the scope calling #eval when evaluating 'return'" do
@@ -257,7 +308,7 @@ describe "Kernel#eval" do
it "has the correct default definee when called through Method#call" do
class EvalSpecs
method(:eval).call("def eval_spec_method_call; end")
- EvalSpecs.should have_instance_method(:eval_spec_method_call)
+ EvalSpecs.should.method_defined?(:eval_spec_method_call, false)
end
end
@@ -311,8 +362,10 @@ end
CODE
code.encoding.should == Encoding::BINARY
eval(code)
- EvalSpecs.constants(false).should include(:"Vπ")
+ EvalSpecs.constants(false).should.include?(:"Vπ")
EvalSpecs::Vπ.should == 3.14
+ ensure
+ EvalSpecs.send(:remove_const, :Vπ)
end
it "allows an emacs-style magic comment encoding" do
@@ -324,8 +377,10 @@ end
CODE
code.encoding.should == Encoding::BINARY
eval(code)
- EvalSpecs.constants(false).should include(:"Vπemacs")
+ EvalSpecs.constants(false).should.include?(:"Vπemacs")
EvalSpecs::Vπemacs.should == 3.14
+ ensure
+ EvalSpecs.send(:remove_const, :Vπemacs)
end
it "allows spaces before the magic encoding comment" do
@@ -337,8 +392,10 @@ end
CODE
code.encoding.should == Encoding::BINARY
eval(code)
- EvalSpecs.constants(false).should include(:"Vπspaces")
+ EvalSpecs.constants(false).should.include?(:"Vπspaces")
EvalSpecs::Vπspaces.should == 3.14
+ ensure
+ EvalSpecs.send(:remove_const, :Vπspaces)
end
it "allows a shebang line before the magic encoding comment" do
@@ -351,8 +408,10 @@ end
CODE
code.encoding.should == Encoding::BINARY
eval(code)
- EvalSpecs.constants(false).should include(:"Vπshebang")
+ EvalSpecs.constants(false).should.include?(:"Vπshebang")
EvalSpecs::Vπshebang.should == 3.14
+ ensure
+ EvalSpecs.send(:remove_const, :Vπshebang)
end
it "allows a shebang line and some spaces before the magic encoding comment" do
@@ -365,8 +424,10 @@ end
CODE
code.encoding.should == Encoding::BINARY
eval(code)
- EvalSpecs.constants(false).should include(:"Vπshebang_spaces")
+ EvalSpecs.constants(false).should.include?(:"Vπshebang_spaces")
EvalSpecs::Vπshebang_spaces.should == 3.14
+ ensure
+ EvalSpecs.send(:remove_const, :Vπshebang_spaces)
end
it "allows a magic encoding comment and a subsequent frozen_string_literal magic comment" do
@@ -381,10 +442,12 @@ end
CODE
code.encoding.should == Encoding::BINARY
eval(code)
- EvalSpecs.constants(false).should include(:"Vπstring")
+ EvalSpecs.constants(false).should.include?(:"Vπstring")
EvalSpecs::Vπstring.should == "frozen"
EvalSpecs::Vπstring.encoding.should == Encoding::UTF_8
EvalSpecs::Vπstring.frozen?.should == !frozen_string_default
+ ensure
+ EvalSpecs.send(:remove_const, :Vπstring)
end
it "allows a magic encoding comment and a frozen_string_literal magic comment on the same line in emacs style" do
@@ -396,10 +459,12 @@ end
CODE
code.encoding.should == Encoding::BINARY
eval(code)
- EvalSpecs.constants(false).should include(:"Vπsame_line")
+ EvalSpecs.constants(false).should.include?(:"Vπsame_line")
EvalSpecs::Vπsame_line.should == "frozen"
EvalSpecs::Vπsame_line.encoding.should == Encoding::UTF_8
- EvalSpecs::Vπsame_line.frozen?.should be_true
+ EvalSpecs::Vπsame_line.frozen?.should == true
+ ensure
+ EvalSpecs.send(:remove_const, :Vπsame_line)
end
it "ignores the magic encoding comment if it is after a frozen_string_literal magic comment" do
@@ -413,13 +478,15 @@ end
CODE
code.encoding.should == Encoding::BINARY
eval(code)
- EvalSpecs.constants(false).should_not include(:"Vπfrozen_first")
+ EvalSpecs.constants(false).should_not.include?(:"Vπfrozen_first")
binary_constant = "Vπfrozen_first".b.to_sym
- EvalSpecs.constants(false).should include(binary_constant)
+ EvalSpecs.constants(false).should.include?(binary_constant)
value = EvalSpecs.const_get(binary_constant)
value.should == "frozen"
value.encoding.should == Encoding::BINARY
value.frozen?.should == !frozen_string_default
+ ensure
+ EvalSpecs.send(:remove_const, binary_constant)
end
it "ignores the frozen_string_literal magic comment if it appears after a token and warns if $VERBOSE is true" do