require 'test/unit' require 'stringio' class TestParse < Test::Unit::TestCase def setup @verbose = $VERBOSE $VERBOSE = nil end def teardown $VERBOSE = @verbose end def test_else_without_rescue x = eval <<-END, nil, __FILE__, __LINE__+1 begin else 42 end END assert_equal(42, x) end def test_alias_backref assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 alias $foo $1 END end end def test_command_call t = Object.new def t.foo(x); x; end a = false b = c = d = true assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 a &&= t.foo 42 b &&= t.foo 42 c &&= t.foo nil d &&= t.foo false END end assert_equal([false, 42, nil, false], [a, b, c, d]) a = 3 assert_nothing_raised { eval("a &= t.foo 5") } assert_equal(1, a) a = [nil, nil, true, true] assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 a[0] ||= t.foo 42 a[1] &&= t.foo 42 a[2] ||= t.foo 42 a[3] &&= t.foo 42 END end assert_equal([42, nil, true, 42], a) o = Object.new class << o attr_accessor :foo, :bar, :Foo, :Bar, :baz, :qux end o.foo = o.Foo = o::baz = nil o.bar = o.Bar = o::qux = 1 assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 o.foo ||= t.foo 42 o.bar &&= t.foo 42 o.Foo ||= t.foo 42 o.Bar &&= t.foo 42 o::baz ||= t.foo 42 o::qux &&= t.foo 42 END end assert_equal([42, 42], [o.foo, o.bar]) assert_equal([42, 42], [o.Foo, o.Bar]) assert_equal([42, 42], [o::baz, o::qux]) assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 $1 ||= t.foo 42 END end def t.bar(x); x + yield; end a = b = nil assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 a = t.bar "foo" do "bar" end.gsub "ob", "OB" b = t.bar "foo" do "bar" end::gsub "ob", "OB" END end assert_equal("foOBar", a) assert_equal("foOBar", b) a = nil assert_nothing_raised do t.instance_eval <<-END, __FILE__, __LINE__+1 a = bar "foo" do "bar" end END end assert_equal("foobar", a) a = nil assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 a = t::bar "foo" do "bar" end END end assert_equal("foobar", a) def t.baz(*r) @baz = r + (block_given? ? [yield] : []) end assert_nothing_raised do t.instance_eval "baz (1), 2" end assert_equal([1, 2], t.instance_eval { @baz }) end def test_mlhs_node c = Class.new class << c attr_accessor :foo, :bar, :Foo, :Bar FOO = BAR = nil end assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 c::foo, c::bar = 1, 2 c.Foo, c.Bar = 1, 2 c::FOO, c::BAR = 1, 2 END end assert_equal([1, 2], [c::foo, c::bar]) assert_equal([1, 2], [c.Foo, c.Bar]) assert_equal([1, 2], [c::FOO, c::BAR]) end def test_dynamic_constant_assignment assert_raise(SyntaxError) do Object.new.instance_eval <<-END, __FILE__, __LINE__+1 def foo self::FOO, self::BAR = 1, 2 ::FOO, ::BAR = 1, 2 end END end assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 $1, $2 = 1, 2 END end assert_raise(SyntaxError) do Object.new.instance_eval <<-END, __FILE__, __LINE__+1 def foo ::FOO = 1 end END end c = Class.new assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 c::FOO &= 1 ::FOO &= 1 END end c = Class.new assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 $1 &= 1 END end end def test_class_module assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 class foo; end END end assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 def foo class Foo; end module Bar; end end END end assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 class Foo Bar; end END end end def test_op_name o = Object.new def o.>(x); x; end def o./(x); x; end a = nil assert_nothing_raised do o.instance_eval <<-END, __FILE__, __LINE__+1 undef >, / END end end def test_arg o = Object.new class << o attr_accessor :foo, :bar, :Foo, :Bar, :baz, :qux end o.foo = o.Foo = o::baz = nil o.bar = o.Bar = o::qux = 1 assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 o.foo ||= 42 o.bar &&= 42 o.Foo ||= 42 o.Bar &&= 42 o::baz ||= 42 o::qux &&= 42 END end assert_equal([42, 42], [o.foo, o.bar]) assert_equal([42, 42], [o.Foo, o.Bar]) assert_equal([42, 42], [o::baz, o::qux]) a = nil assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 a = -2.0 ** 2 END end assert_equal(-4.0, a) end def test_block_variable o = Object.new def o.foo(*r); yield(*r); end a = nil assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 o.foo 1 do|; a| a = 42 end END end assert_nil(a) end def test_bad_arg assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 def foo(FOO); end END end assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 def foo(@foo); end END end assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 def foo($foo); end END end assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 def foo(@@foo); end END end o = Object.new def o.foo(*r); yield(*r); end assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 o.foo 1 {|; @a| @a = 42 } END end end def test_do_lambda a = b = nil assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 a = -> do b = 42 end END end a.call assert_equal(42, b) end def test_block_call_colon2 o = Object.new def o.foo(x); x + yield; end a = b = nil assert_nothing_raised do o.instance_eval <<-END, __FILE__, __LINE__+1 a = foo 1 do 42 end.to_s b = foo 1 do 42 end::to_s END end assert_equal("43", a) assert_equal("43", b) end def test_call_method a = b = nil assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 a = proc {|x| x + "bar" }.("foo") b = proc {|x| x + "bar" }::("foo") END end assert_equal("foobar", a) assert_equal("foobar", b) end def test_xstring assert_raise(Errno::ENOENT) do eval("``") end end def test_words assert_equal([], %W( )) end def test_dstr @@foo = 1 assert_equal("foo 1 bar", "foo #@@foo bar") "1" =~ /(.)/ assert_equal("foo 1 bar", "foo #$1 bar") end def test_dsym assert_nothing_raised { eval(':""') } end def test_arg2 o = Object.new assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 def o.foo(a=42,*r,z,&b); b.call(r.inject(a*1000+z*100, :+)); end END end assert_equal(-1405, o.foo(1,2,3,4) {|x| -x }) assert_equal(-1302, o.foo(1,2,3) {|x| -x }) assert_equal(-1200, o.foo(1,2) {|x| -x }) assert_equal(-42100, o.foo(1) {|x| -x }) assert_raise(ArgumentError) { o.foo() } assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 def o.foo(a=42,z,&b); b.call(a*1000+z*100); end END end assert_equal(-1200, o.foo(1,2) {|x| -x } ) assert_equal(-42100, o.foo(1) {|x| -x } ) assert_raise(ArgumentError) { o.foo() } assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 def o.foo(*r,z,&b); b.call(r.inject(z*100, :+)); end END end assert_equal(-303, o.foo(1,2,3) {|x| -x } ) assert_equal(-201, o.foo(1,2) {|x| -x } ) assert_equal(-100, o.foo(1) {|x| -x } ) assert_raise(ArgumentError) { o.foo() } end def test_duplicate_argument assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 1.times {|&b?| } END end assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 1.times {|a, a|} END end assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 def foo(a, a); end END end end def test_define_singleton_error assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 def ("foo").foo; end END end end def test_backquote t = Object.new assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 def t.`(x); "foo" + x + "bar"; end END end a = b = nil assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 a = t.` "zzz" 1.times {|;z| t.` ("zzz") } END t.instance_eval <<-END, __FILE__, __LINE__+1 b = `zzz` END end assert_equal("foozzzbar", a) assert_equal("foozzzbar", b) end def test_carrige_return assert_equal(2, eval("1 +\r\n1")) end def test_string assert_raise(SyntaxError) do eval '"\xg1"' end assert_raise(SyntaxError) do eval '"\u{1234"' end assert_raise(SyntaxError) do eval '"\M1"' end assert_raise(SyntaxError) do eval '"\C1"' end assert_equal("\x81", eval('"\C-\M-a"')) assert_equal("\177", eval('"\c?"')) end def test_question assert_raise(SyntaxError) { eval('?') } assert_raise(SyntaxError) { eval('? ') } assert_raise(SyntaxError) { eval("?\n") } assert_raise(SyntaxError) { eval("?\t") } assert_raise(SyntaxError) { eval("?\v") } assert_raise(SyntaxError) { eval("?\r") } assert_raise(SyntaxError) { eval("?\f") } assert_equal("\u{1234}", eval("?\u{1234}")) assert_equal("\u{1234}", eval('?\u{1234}')) end def test_percent assert_equal(:foo, eval('%s(foo)')) assert_raise(SyntaxError) { eval('%s') } assert_raise(SyntaxError) { eval('%ss') } assert_raise(SyntaxError) { eval('%z()') } end def test_symbol bug = '[ruby-dev:41447]' sym = "foo\0bar".to_sym assert_nothing_raised(SyntaxError, bug) do assert_equal(sym, eval(":'foo\0bar'")) end assert_nothing_raised(SyntaxError, bug) do assert_equal(sym, eval(':"foo\u0000bar"')) end assert_nothing_raised(SyntaxError, bug) do assert_equal(sym, eval(':"foo\u{0}bar"')) end assert_raise(SyntaxError) do eval ':"foo\u{}bar"' end end def test_parse_string assert_raise(SyntaxError) do eval <<-END, nil, __FILE__, __LINE__+1 / END end end def test_here_document x = nil assert_raise(SyntaxError) do eval %Q( <\