diff options
Diffstat (limited to 'spec/ruby/core/kernel/eval_spec.rb')
-rw-r--r-- | spec/ruby/core/kernel/eval_spec.rb | 149 |
1 files changed, 99 insertions, 50 deletions
diff --git a/spec/ruby/core/kernel/eval_spec.rb b/spec/ruby/core/kernel/eval_spec.rb index c53e51e430..454bc4a58e 100644 --- a/spec/ruby/core/kernel/eval_spec.rb +++ b/spec/ruby/core/kernel/eval_spec.rb @@ -135,7 +135,7 @@ describe "Kernel#eval" do it "includes file and line information in syntax error" do expected = 'speccing.rb' -> { - eval('if true',TOPLEVEL_BINDING, expected) + eval('if true', TOPLEVEL_BINDING, expected) }.should raise_error(SyntaxError) { |e| e.message.should =~ /#{expected}:1:.+/ } @@ -144,7 +144,7 @@ describe "Kernel#eval" do it "evaluates string with given filename and negative linenumber" do expected_file = 'speccing.rb' -> { - eval('if true',TOPLEVEL_BINDING, expected_file, -100) + eval('if true', TOPLEVEL_BINDING, expected_file, -100) }.should raise_error(SyntaxError) { |e| e.message.should =~ /#{expected_file}:-100:.+/ } @@ -159,18 +159,7 @@ describe "Kernel#eval" do end end - ruby_version_is ""..."3.0" do - it "uses the filename of the binding if none is provided" do - eval("__FILE__").should == "(eval)" - suppress_warning {eval("__FILE__", binding)}.should == __FILE__ - eval("__FILE__", binding, "success").should == "success" - suppress_warning {eval("eval '__FILE__', binding")}.should == "(eval)" - suppress_warning {eval("eval '__FILE__', binding", binding)}.should == __FILE__ - suppress_warning {eval("eval '__FILE__', binding", binding, 'success')}.should == 'success' - end - end - - ruby_version_is "3.0" do + ruby_version_is ""..."3.3" do it "uses (eval) filename if none is provided" do eval("__FILE__").should == "(eval)" eval("__FILE__", binding).should == "(eval)" @@ -180,8 +169,27 @@ describe "Kernel#eval" do eval("eval '__FILE__', binding", binding, 'success').should == '(eval)' eval("eval '__FILE__', binding, 'success'", binding).should == 'success' end + + it 'uses (eval) for __FILE__ and 1 for __LINE__ with a binding argument' do + eval("[__FILE__, __LINE__]", binding).should == ["(eval)", 1] + 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' + 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 + end # Found via Rubinius bug github:#149 it "does not alter the value of __FILE__ in the binding" do first_time = EvalSpecs.call_eval @@ -218,6 +226,20 @@ describe "Kernel#eval" do -> { eval("return :eval") }.call.should == :eval end + it "returns from the method calling #eval when evaluating 'return'" do + def eval_return(n) + eval("return n*2") + end + -> { eval_return(3) }.call.should == 6 + end + + it "returns from the method calling #eval when evaluating 'return' in BEGIN" do + def eval_return(n) + eval("BEGIN {return n*3}") + end + -> { eval_return(4) }.call.should == 12 + end + it "unwinds through a Proc-style closure and returns from a lambda-style closure in the closure chain" do code = fixture __FILE__, "eval_return_with_lambda.rb" ruby_exe(code).chomp.should == "a,b,c,eval,f" @@ -228,6 +250,30 @@ describe "Kernel#eval" do ruby_exe(code).chomp.should == "a,b,c,e,LocalJumpError,f" end + it "can be called with Method#call" do + method(:eval).call("2 * 3").should == 6 + end + + 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) + end + end + + it "makes flip-flop operator work correctly" do + ScratchPad.record [] + + eval "10.times { |i| ScratchPad << i if (i == 4)...(i == 4) }" + ScratchPad.recorded.should == [4, 5, 6, 7, 8, 9] + + ScratchPad.clear + end + + it "returns nil if given an empty string" do + eval("").should == nil + end + # See language/magic_comment_spec.rb for more magic comments specs describe "with a magic encoding comment" do it "uses the magic comment encoding for the encoding of literal strings" do @@ -304,12 +350,11 @@ CODE end it "allows a magic encoding comment and a subsequent frozen_string_literal magic comment" do - # Make sure frozen_string_literal is not default true - eval("'foo'".b).frozen?.should be_false + frozen_string_default = "test".frozen? code = <<CODE.b # encoding: UTF-8 -# frozen_string_literal: true +# frozen_string_literal: #{!frozen_string_default} class EvalSpecs Vπstring = "frozen" end @@ -319,7 +364,7 @@ CODE 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 be_true + EvalSpecs::Vπstring.frozen?.should == !frozen_string_default end it "allows a magic encoding comment and a frozen_string_literal magic comment on the same line in emacs style" do @@ -338,8 +383,9 @@ CODE end it "ignores the magic encoding comment if it is after a frozen_string_literal magic comment" do + frozen_string_default = "test".frozen? code = <<CODE.b -# frozen_string_literal: true +# frozen_string_literal: #{!frozen_string_default} # encoding: UTF-8 class EvalSpecs Vπfrozen_first = "frozen" @@ -353,64 +399,67 @@ CODE value = EvalSpecs.const_get(binary_constant) value.should == "frozen" value.encoding.should == Encoding::BINARY - value.frozen?.should be_true + value.frozen?.should == !frozen_string_default end it "ignores the frozen_string_literal magic comment if it appears after a token and warns if $VERBOSE is true" do + frozen_string_default = "test".frozen? code = <<CODE some_token_before_magic_comment = :anything -# frozen_string_literal: true +# frozen_string_literal: #{!frozen_string_default} class EvalSpecs Vπstring_not_frozen = "not frozen" end CODE - -> { eval(code) }.should complain(/warning: `frozen_string_literal' is ignored after any tokens/, verbose: true) - EvalSpecs::Vπstring_not_frozen.frozen?.should be_false + -> { eval(code) }.should complain(/warning: [`']frozen_string_literal' is ignored after any tokens/, verbose: true) + EvalSpecs::Vπstring_not_frozen.frozen?.should == frozen_string_default EvalSpecs.send :remove_const, :Vπstring_not_frozen -> { eval(code) }.should_not complain(verbose: false) - EvalSpecs::Vπstring_not_frozen.frozen?.should be_false + EvalSpecs::Vπstring_not_frozen.frozen?.should == frozen_string_default EvalSpecs.send :remove_const, :Vπstring_not_frozen end end - it "activates refinements from the eval scope" do - refinery = Module.new do - refine EvalSpecs::A do - def foo - "bar" + describe 'with refinements' do + it "activates refinements from the eval scope" do + refinery = Module.new do + refine EvalSpecs::A do + def foo + "bar" + end end end - end - result = nil + result = nil - Module.new do - using refinery + Module.new do + using refinery - result = eval "EvalSpecs::A.new.foo" - end + result = eval "EvalSpecs::A.new.foo" + end - result.should == "bar" - end + result.should == "bar" + end - it "activates refinements from the binding" do - refinery = Module.new do - refine EvalSpecs::A do - def foo - "bar" + it "activates refinements from the binding" do + refinery = Module.new do + refine EvalSpecs::A do + def foo + "bar" + end end end - end - b = nil - m = Module.new do - using refinery - b = binding - end + b = nil + m = Module.new do + using refinery + b = binding + end - result = eval "EvalSpecs::A.new.foo", b + result = eval "EvalSpecs::A.new.foo", b - result.should == "bar" + result.should == "bar" + end end end |