1# coding: US-ASCII
2require 'test/unit'
3require 'stringio'
4
5class TestParse < Test::Unit::TestCase
6  def setup
7    @verbose = $VERBOSE
8    $VERBOSE = nil
9  end
10
11  def teardown
12    $VERBOSE = @verbose
13  end
14
15  def test_else_without_rescue
16    x = eval <<-END, nil, __FILE__, __LINE__+1
17      begin
18      else
19        42
20      end
21    END
22    assert_equal(42, x)
23  end
24
25  def test_alias_backref
26    assert_raise(SyntaxError) do
27      eval <<-END, nil, __FILE__, __LINE__+1
28        alias $foo $1
29      END
30    end
31  end
32
33  def test_command_call
34    t = Object.new
35    def t.foo(x); x; end
36
37    a = false
38    b = c = d = true
39    assert_nothing_raised do
40      eval <<-END, nil, __FILE__, __LINE__+1
41        a &&= t.foo 42
42        b &&= t.foo 42
43        c &&= t.foo nil
44        d &&= t.foo false
45      END
46    end
47    assert_equal([false, 42, nil, false], [a, b, c, d])
48
49    a = 3
50    assert_nothing_raised { eval("a &= t.foo 5") }
51    assert_equal(1, a)
52
53    a = [nil, nil, true, true]
54    assert_nothing_raised do
55      eval <<-END, nil, __FILE__, __LINE__+1
56        a[0] ||= t.foo 42
57        a[1] &&= t.foo 42
58        a[2] ||= t.foo 42
59        a[3] &&= t.foo 42
60      END
61    end
62    assert_equal([42, nil, true, 42], a)
63
64    o = Object.new
65    class << o
66      attr_accessor :foo, :bar, :Foo, :Bar, :baz, :qux
67    end
68    o.foo = o.Foo = o::baz = nil
69    o.bar = o.Bar = o::qux = 1
70    assert_nothing_raised do
71      eval <<-END, nil, __FILE__, __LINE__+1
72        o.foo ||= t.foo 42
73        o.bar &&= t.foo 42
74        o.Foo ||= t.foo 42
75        o.Bar &&= t.foo 42
76        o::baz ||= t.foo 42
77        o::qux &&= t.foo 42
78      END
79    end
80    assert_equal([42, 42], [o.foo, o.bar])
81    assert_equal([42, 42], [o.Foo, o.Bar])
82    assert_equal([42, 42], [o::baz, o::qux])
83
84    assert_raise(SyntaxError) do
85      eval <<-END, nil, __FILE__, __LINE__+1
86        $1 ||= t.foo 42
87      END
88    end
89
90    def t.bar(x); x + yield; end
91
92    a = b = nil
93    assert_nothing_raised do
94      eval <<-END, nil, __FILE__, __LINE__+1
95        a = t.bar "foo" do
96          "bar"
97        end.gsub "ob", "OB"
98        b = t.bar "foo" do
99          "bar"
100        end::gsub "ob", "OB"
101      END
102    end
103    assert_equal("foOBar", a)
104    assert_equal("foOBar", b)
105
106    a = nil
107    assert_nothing_raised do
108      t.instance_eval <<-END, __FILE__, __LINE__+1
109        a = bar "foo" do "bar" end
110      END
111    end
112    assert_equal("foobar", a)
113
114    a = nil
115    assert_nothing_raised do
116      eval <<-END, nil, __FILE__, __LINE__+1
117        a = t::bar "foo" do "bar" end
118      END
119    end
120    assert_equal("foobar", a)
121
122    def t.baz(*r)
123      @baz = r + (block_given? ? [yield] : [])
124    end
125
126    assert_nothing_raised do
127      t.instance_eval "baz (1), 2"
128    end
129    assert_equal([1, 2], t.instance_eval { @baz })
130  end
131
132  def test_mlhs_node
133    c = Class.new
134    class << c
135      attr_accessor :foo, :bar, :Foo, :Bar
136      FOO = BAR = nil
137    end
138
139    assert_nothing_raised do
140      eval <<-END, nil, __FILE__, __LINE__+1
141        c::foo, c::bar = 1, 2
142        c.Foo, c.Bar = 1, 2
143        c::FOO, c::BAR = 1, 2
144      END
145    end
146    assert_equal([1, 2], [c::foo, c::bar])
147    assert_equal([1, 2], [c.Foo, c.Bar])
148    assert_equal([1, 2], [c::FOO, c::BAR])
149  end
150
151  def test_dynamic_constant_assignment
152    assert_raise(SyntaxError) do
153      Object.new.instance_eval <<-END, __FILE__, __LINE__+1
154        def foo
155          self::FOO, self::BAR = 1, 2
156          ::FOO, ::BAR = 1, 2
157        end
158      END
159    end
160
161    assert_raise(SyntaxError) do
162      eval <<-END, nil, __FILE__, __LINE__+1
163        $1, $2 = 1, 2
164      END
165    end
166
167    assert_raise(SyntaxError) do
168      Object.new.instance_eval <<-END, __FILE__, __LINE__+1
169        def foo
170          ::FOO = 1
171        end
172      END
173    end
174
175    c = Class.new
176    assert_nothing_raised(SyntaxError) do
177      eval <<-END, nil, __FILE__, __LINE__+1
178      if false
179        c::FOO &= 1
180        ::FOO &= 1
181      end
182      END
183    end
184
185    c = Class.new
186    assert_raise(SyntaxError) do
187      eval <<-END, nil, __FILE__, __LINE__+1
188        $1 &= 1
189      END
190    end
191  end
192
193  def test_class_module
194    assert_raise(SyntaxError) do
195      eval <<-END, nil, __FILE__, __LINE__+1
196        class foo; end
197      END
198    end
199
200    assert_raise(SyntaxError) do
201      eval <<-END, nil, __FILE__, __LINE__+1
202        def foo
203          class Foo; end
204          module Bar; end
205        end
206      END
207    end
208
209    assert_raise(SyntaxError) do
210      eval <<-END, nil, __FILE__, __LINE__+1
211        class Foo Bar; end
212      END
213    end
214  end
215
216  def test_op_name
217    o = Object.new
218    def o.>(x); x; end
219    def o./(x); x; end
220
221    a = nil
222    assert_nothing_raised do
223      o.instance_eval <<-END, __FILE__, __LINE__+1
224        undef >, /
225      END
226    end
227  end
228
229  def test_arg
230    o = Object.new
231    class << o
232      attr_accessor :foo, :bar, :Foo, :Bar, :baz, :qux
233    end
234    o.foo = o.Foo = o::baz = nil
235    o.bar = o.Bar = o::qux = 1
236    assert_nothing_raised do
237      eval <<-END, nil, __FILE__, __LINE__+1
238        o.foo ||= 42
239        o.bar &&= 42
240        o.Foo ||= 42
241        o.Bar &&= 42
242        o::baz ||= 42
243        o::qux &&= 42
244      END
245    end
246    assert_equal([42, 42], [o.foo, o.bar])
247    assert_equal([42, 42], [o.Foo, o.Bar])
248    assert_equal([42, 42], [o::baz, o::qux])
249
250    a = nil
251    assert_nothing_raised do
252      eval <<-END, nil, __FILE__, __LINE__+1
253        a = -2.0 ** 2
254      END
255    end
256    assert_equal(-4.0, a)
257  end
258
259  def test_block_variable
260    o = Object.new
261    def o.foo(*r); yield(*r); end
262
263    a = nil
264    assert_nothing_raised do
265      eval <<-END, nil, __FILE__, __LINE__+1
266        o.foo 1 do|; a| a = 42 end
267      END
268    end
269    assert_nil(a)
270  end
271
272  def test_bad_arg
273    assert_raise(SyntaxError) do
274      eval <<-END, nil, __FILE__, __LINE__+1
275        def foo(FOO); end
276      END
277    end
278
279    assert_raise(SyntaxError) do
280      eval <<-END, nil, __FILE__, __LINE__+1
281        def foo(@foo); end
282      END
283    end
284
285    assert_raise(SyntaxError) do
286      eval <<-END, nil, __FILE__, __LINE__+1
287        def foo($foo); end
288      END
289    end
290
291    assert_raise(SyntaxError) do
292      eval <<-END, nil, __FILE__, __LINE__+1
293        def foo(@@foo); end
294      END
295    end
296
297    o = Object.new
298    def o.foo(*r); yield(*r); end
299
300    assert_raise(SyntaxError) do
301      eval <<-END, nil, __FILE__, __LINE__+1
302        o.foo 1 {|; @a| @a = 42 }
303      END
304    end
305  end
306
307  def test_do_lambda
308    a = b = nil
309    assert_nothing_raised do
310      eval <<-END, nil, __FILE__, __LINE__+1
311        a = -> do
312          b = 42
313        end
314      END
315    end
316    a.call
317    assert_equal(42, b)
318  end
319
320  def test_block_call_colon2
321    o = Object.new
322    def o.foo(x); x + yield; end
323
324    a = b = nil
325    assert_nothing_raised do
326      o.instance_eval <<-END, __FILE__, __LINE__+1
327        a = foo 1 do 42 end.to_s
328        b = foo 1 do 42 end::to_s
329      END
330    end
331    assert_equal("43", a)
332    assert_equal("43", b)
333  end
334
335  def test_call_method
336    a = b = nil
337    assert_nothing_raised do
338      eval <<-END, nil, __FILE__, __LINE__+1
339        a = proc {|x| x + "bar" }.("foo")
340        b = proc {|x| x + "bar" }::("foo")
341      END
342    end
343    assert_equal("foobar", a)
344    assert_equal("foobar", b)
345  end
346
347  def test_xstring
348    assert_raise(Errno::ENOENT) do
349      eval("``")
350    end
351  end
352
353  def test_words
354    assert_equal([], %W( ))
355  end
356
357  def test_dstr
358    @@foo = 1
359    assert_equal("foo 1 bar", "foo #@@foo bar")
360    "1" =~ /(.)/
361    assert_equal("foo 1 bar", "foo #$1 bar")
362  end
363
364  def test_dstr_disallowd_variable
365    bug8375 = '[ruby-core:54885] [Bug #8375]'
366    %w[@ @1 @@. @@ @@1 @@. $ $%].each do |src|
367      src = '#'+src+' '
368      str = assert_nothing_raised(SyntaxError, "#{bug8375} #{src.dump}") do
369        break eval('"'+src+'"')
370      end
371      assert_equal(src, str, bug8375)
372    end
373  end
374
375  def test_dsym
376    assert_nothing_raised { eval(':""') }
377  end
378
379  def test_arg2
380    o = Object.new
381
382    assert_nothing_raised do
383      eval <<-END, nil, __FILE__, __LINE__+1
384        def o.foo(a=42,*r,z,&b); b.call(r.inject(a*1000+z*100, :+)); end
385      END
386    end
387    assert_equal(-1405, o.foo(1,2,3,4) {|x| -x })
388    assert_equal(-1302, o.foo(1,2,3) {|x| -x })
389    assert_equal(-1200, o.foo(1,2) {|x| -x })
390    assert_equal(-42100, o.foo(1) {|x| -x })
391    assert_raise(ArgumentError) { o.foo() }
392
393    assert_nothing_raised do
394      eval <<-END, nil, __FILE__, __LINE__+1
395        def o.foo(a=42,z,&b); b.call(a*1000+z*100); end
396      END
397    end
398    assert_equal(-1200, o.foo(1,2) {|x| -x } )
399    assert_equal(-42100, o.foo(1) {|x| -x } )
400    assert_raise(ArgumentError) { o.foo() }
401
402    assert_nothing_raised do
403      eval <<-END, nil, __FILE__, __LINE__+1
404        def o.foo(*r,z,&b); b.call(r.inject(z*100, :+)); end
405      END
406    end
407    assert_equal(-303, o.foo(1,2,3) {|x| -x } )
408    assert_equal(-201, o.foo(1,2) {|x| -x } )
409    assert_equal(-100, o.foo(1) {|x| -x } )
410    assert_raise(ArgumentError) { o.foo() }
411  end
412
413  def test_duplicate_argument
414    assert_raise(SyntaxError) do
415      eval <<-END, nil, __FILE__, __LINE__+1
416        1.times {|&b?| }
417      END
418    end
419
420    assert_raise(SyntaxError) do
421      eval <<-END, nil, __FILE__, __LINE__+1
422        1.times {|a, a|}
423      END
424    end
425
426    assert_raise(SyntaxError) do
427      eval <<-END, nil, __FILE__, __LINE__+1
428        def foo(a, a); end
429      END
430    end
431  end
432
433  def test_define_singleton_error
434    assert_raise(SyntaxError) do
435      eval <<-END, nil, __FILE__, __LINE__+1
436        def ("foo").foo; end
437      END
438    end
439  end
440
441  def test_backquote
442    t = Object.new
443
444    assert_nothing_raised do
445      eval <<-END, nil, __FILE__, __LINE__+1
446        def t.`(x); "foo" + x + "bar"; end
447      END
448    end
449    a = b = nil
450    assert_nothing_raised do
451      eval <<-END, nil, __FILE__, __LINE__+1
452        a = t.` "zzz"
453        1.times {|;z| t.` ("zzz") }
454      END
455      t.instance_eval <<-END, __FILE__, __LINE__+1
456        b = `zzz`
457      END
458    end
459    assert_equal("foozzzbar", a)
460    assert_equal("foozzzbar", b)
461  end
462
463  def test_carrige_return
464    assert_equal(2, eval("1 +\r\n1"))
465  end
466
467  def test_string
468    assert_raise(SyntaxError) do
469      eval '"\xg1"'
470    end
471
472    assert_raise(SyntaxError) do
473      eval '"\u{1234"'
474    end
475
476    assert_raise(SyntaxError) do
477      eval '"\M1"'
478    end
479
480    assert_raise(SyntaxError) do
481      eval '"\C1"'
482    end
483
484    assert_equal("\x81", eval('"\C-\M-a"'))
485    assert_equal("\177", eval('"\c?"'))
486  end
487
488  def test_question
489    assert_raise(SyntaxError) { eval('?') }
490    assert_raise(SyntaxError) { eval('? ') }
491    assert_raise(SyntaxError) { eval("?\n") }
492    assert_raise(SyntaxError) { eval("?\t") }
493    assert_raise(SyntaxError) { eval("?\v") }
494    assert_raise(SyntaxError) { eval("?\r") }
495    assert_raise(SyntaxError) { eval("?\f") }
496    assert_equal("\u{1234}", eval("?\u{1234}"))
497    assert_equal("\u{1234}", eval('?\u{1234}'))
498  end
499
500  def test_percent
501    assert_equal(:foo, eval('%s(foo)'))
502    assert_raise(SyntaxError) { eval('%s') }
503    assert_raise(SyntaxError) { eval('%ss') }
504    assert_raise(SyntaxError) { eval('%z()') }
505  end
506
507  def test_symbol
508    bug = '[ruby-dev:41447]'
509    sym = "foo\0bar".to_sym
510    assert_nothing_raised(SyntaxError, bug) do
511      assert_equal(sym, eval(":'foo\0bar'"))
512    end
513    assert_nothing_raised(SyntaxError, bug) do
514      assert_equal(sym, eval(':"foo\u0000bar"'))
515    end
516    assert_nothing_raised(SyntaxError, bug) do
517      assert_equal(sym, eval(':"foo\u{0}bar"'))
518    end
519    assert_raise(SyntaxError) do
520      eval ':"foo\u{}bar"'
521    end
522  end
523
524  def test_parse_string
525    assert_raise(SyntaxError) do
526      eval <<-END, nil, __FILE__, __LINE__+1
527/
528      END
529    end
530  end
531
532  def test_here_document
533    x = nil
534
535    assert_raise(SyntaxError) do
536      eval %Q(
537<\<FOO
538      )
539    end
540
541    assert_nothing_raised(SyntaxError) do
542      x = eval %q(
543<<FOO
544#$
545FOO
546      )
547    end
548    assert_equal "\#$\n", x
549
550    assert_raise(SyntaxError) do
551      eval %Q(
552<\<\"
553      )
554    end
555
556    assert_raise(SyntaxError) do
557      eval %q(
558<<``
559      )
560    end
561
562    assert_raise(SyntaxError) do
563      eval %q(
564<<--
565      )
566    end
567
568    assert_nothing_raised(SyntaxError) do
569      x = eval %q(
570<<FOO
571#$
572foo
573FOO
574      )
575    end
576    assert_equal "\#$\nfoo\n", x
577
578    assert_nothing_raised do
579      eval "x = <<""FOO\r\n1\r\nFOO"
580    end
581    assert_equal("1\n", x)
582  end
583
584  def test_magic_comment
585    x = nil
586    assert_nothing_raised do
587      eval <<-END, nil, __FILE__, __LINE__+1
588# coding = utf-8
589x = __ENCODING__
590      END
591    end
592    assert_equal(Encoding.find("UTF-8"), x)
593
594    assert_raise(ArgumentError) do
595      eval <<-END, nil, __FILE__, __LINE__+1
596# coding = foobarbazquxquux_dummy_enconding
597x = __ENCODING__
598      END
599    end
600  end
601
602  def test_utf8_bom
603    x = nil
604    assert_nothing_raised do
605      eval "\xef\xbb\xbf x = __ENCODING__"
606    end
607    assert_equal(Encoding.find("UTF-8"), x)
608    assert_raise(NameError) { eval "\xef" }
609  end
610
611  def test_dot_in_next_line
612    x = nil
613    assert_nothing_raised do
614      eval <<-END, nil, __FILE__, __LINE__+1
615        x = 1
616        .to_s
617      END
618    end
619    assert_equal("1", x)
620  end
621
622  def test_pow_asgn
623    x = 3
624    assert_nothing_raised { eval("x **= 2") }
625    assert_equal(9, x)
626  end
627
628  def test_embedded_rd
629    assert_raise(SyntaxError) do
630      eval <<-END, nil, __FILE__, __LINE__+1
631=begin
632      END
633    end
634  end
635
636  def test_float
637    assert_equal(1.0/0, eval("1e10000"))
638    assert_raise(SyntaxError) { eval('1_E') }
639    assert_raise(SyntaxError) { eval('1E1E1') }
640  end
641
642  def test_global_variable
643    assert_equal(nil, eval('$-x'))
644    assert_equal(nil, eval('alias $preserve_last_match $&'))
645    assert_equal(nil, eval('alias $& $test_parse_foobarbazqux'))
646    $test_parse_foobarbazqux = nil
647    assert_equal(nil, $&)
648    assert_equal(nil, eval('alias $& $preserve_last_match'))
649    assert_raise(SyntaxError) { eval('$#') }
650  end
651
652  def test_invalid_instance_variable
653    assert_raise(SyntaxError) { eval('@#') }
654  end
655
656  def test_invalid_class_variable
657    assert_raise(SyntaxError) { eval('@@1') }
658  end
659
660  def test_invalid_char
661    x = 1
662    assert_equal(1, eval("\x01x"))
663    assert_equal(nil, eval("\x04x"))
664  end
665
666  def test_literal_concat
667    x = "baz"
668    assert_equal("foobarbaz", eval('"foo" "bar#{x}"'))
669  end
670
671  def test_unassignable
672    assert_raise(SyntaxError) do
673      eval %q(self = 1)
674    end
675    assert_raise(SyntaxError) do
676      eval %q(nil = 1)
677    end
678    assert_raise(SyntaxError) do
679      eval %q(true = 1)
680    end
681    assert_raise(SyntaxError) do
682      eval %q(false = 1)
683    end
684    assert_raise(SyntaxError) do
685      eval %q(__FILE__ = 1)
686    end
687    assert_raise(SyntaxError) do
688      eval %q(__LINE__ = 1)
689    end
690    assert_raise(SyntaxError) do
691      eval %q(__ENCODING__ = 1)
692    end
693    assert_raise(SyntaxError) do
694      eval <<-END, nil, __FILE__, __LINE__+1
695        def foo
696          FOO = 1
697        end
698      END
699    end
700  end
701
702  def test_block_dup
703    assert_raise(SyntaxError) do
704      eval <<-END, nil, __FILE__, __LINE__+1
705        foo(&proc{}) {}
706      END
707    end
708  end
709
710  def test_set_backref
711    assert_raise(SyntaxError) do
712      eval <<-END, nil, __FILE__, __LINE__+1
713        $& = 1
714      END
715    end
716  end
717
718  def test_arg_concat
719    o = Object.new
720    class << o; self; end.instance_eval do
721      define_method(:[]=) {|*r, &b| b.call(r) }
722    end
723    r = nil
724    assert_nothing_raised do
725      eval <<-END, nil, __FILE__, __LINE__+1
726        o[&proc{|x| r = x }] = 1
727      END
728    end
729    assert_equal([1], r)
730  end
731
732  def test_void_expr_stmts_value
733    # This test checks if void contexts are warned correctly.
734    # Thus, warnings MUST NOT be suppressed.
735    $VERBOSE = true
736    stderr = $stderr
737    $stderr = StringIO.new("")
738    x = 1
739    assert_nil eval("x; nil")
740    assert_nil eval("1+1; nil")
741    assert_nil eval("TestParse; nil")
742    assert_nil eval("::TestParse; nil")
743    assert_nil eval("x..x; nil")
744    assert_nil eval("x...x; nil")
745    assert_nil eval("self; nil")
746    assert_nil eval("nil; nil")
747    assert_nil eval("true; nil")
748    assert_nil eval("false; nil")
749    assert_nil eval("defined?(1); nil")
750
751    assert_raise(SyntaxError) do
752      eval %q(1; next; 2)
753    end
754
755    o = Object.new
756    assert_nothing_raised do
757      eval <<-END, nil, __FILE__, __LINE__+1
758        x = def o.foo; end
759      END
760    end
761    assert_equal(14, $stderr.string.lines.to_a.size)
762    $stderr = stderr
763  end
764
765  def test_assign_in_conditional
766    assert_raise(SyntaxError) do
767      eval <<-END, nil, __FILE__, __LINE__+1
768        (x, y = 1, 2) ? 1 : 2
769      END
770    end
771
772    assert_nothing_raised do
773      eval <<-END, nil, __FILE__, __LINE__+1
774        if @x = true
775          1
776        else
777          2
778        end
779      END
780    end
781  end
782
783  def test_literal_in_conditional
784    assert_nothing_raised do
785      eval <<-END, nil, __FILE__, __LINE__+1
786        "foo" ? 1 : 2
787      END
788    end
789
790    assert_nothing_raised do
791      x = "bar"
792      eval <<-END, nil, __FILE__, __LINE__+1
793        /foo#{x}baz/ ? 1 : 2
794      END
795    end
796
797    assert_nothing_raised do
798      eval <<-END, nil, __FILE__, __LINE__+1
799        (true..false) ? 1 : 2
800      END
801    end
802
803    assert_nothing_raised do
804      eval <<-END, nil, __FILE__, __LINE__+1
805        ("foo".."bar") ? 1 : 2
806      END
807    end
808
809    assert_nothing_raised do
810      x = "bar"
811      eval <<-END, nil, __FILE__, __LINE__+1
812        :"foo#{"x"}baz" ? 1 : 2
813      END
814    end
815  end
816
817  def test_no_blockarg
818    assert_raise(SyntaxError) do
819      eval <<-END, nil, __FILE__, __LINE__+1
820        yield(&:+)
821      END
822    end
823  end
824
825  def test_intern
826    assert_equal(':""', ''.intern.inspect)
827    assert_equal(':$foo', '$foo'.intern.inspect)
828    assert_equal(':"!foo"', '!foo'.intern.inspect)
829    assert_equal(':"foo=="', "foo==".intern.inspect)
830  end
831
832  def test_all_symbols
833    x = Symbol.all_symbols
834    assert_kind_of(Array, x)
835    assert(x.all? {|s| s.is_a?(Symbol) })
836  end
837
838  def test_is_class_id
839    c = Class.new
840    assert_raise(NameError) do
841      c.instance_eval { remove_class_variable(:@var) }
842    end
843  end
844
845  def test_method_block_location
846    bug5614 = '[ruby-core:40936]'
847    expected = nil
848    e = assert_raise(NoMethodError) do
849      1.times do
850        expected = __LINE__+1
851      end.print do
852        #
853      end
854    end
855    actual = e.backtrace.first[/\A#{Regexp.quote(__FILE__)}:(\d+):/o, 1].to_i
856    assert_equal(expected, actual, bug5614)
857  end
858end
859