2010-07-04 09:50:34 -04:00
|
|
|
require 'test/unit'
|
2012-03-15 02:37:46 -04:00
|
|
|
require_relative 'envutil'
|
2010-07-04 09:50:34 -04:00
|
|
|
|
|
|
|
class TestSyntax < Test::Unit::TestCase
|
2012-03-05 11:17:29 -05:00
|
|
|
def assert_valid_syntax(code, fname, mesg = fname)
|
2010-07-04 09:50:34 -04:00
|
|
|
code = code.dup.force_encoding("ascii-8bit")
|
|
|
|
code.sub!(/\A(?:\xef\xbb\xbf)?(\s*\#.*$)*(\n)?/n) {
|
|
|
|
"#$&#{"\n" if $1 && !$2}BEGIN{throw tag, :ok}\n"
|
|
|
|
}
|
|
|
|
code.force_encoding("us-ascii")
|
2012-03-05 11:17:29 -05:00
|
|
|
verbose, $VERBOSE = $VERBOSE, nil
|
2012-03-15 02:37:46 -04:00
|
|
|
yield if defined?(yield)
|
2012-03-05 11:17:29 -05:00
|
|
|
assert_nothing_raised(SyntaxError, mesg) do
|
|
|
|
assert_equal(:ok, catch {|tag| eval(code, binding, fname, 0)}, mesg)
|
|
|
|
end
|
|
|
|
ensure
|
|
|
|
$VERBOSE = verbose
|
2010-07-04 09:50:34 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_syntax
|
|
|
|
assert_nothing_raised(Exception) do
|
|
|
|
for script in Dir[File.expand_path("../../../{lib,sample,ext,test}/**/*.rb", __FILE__)].sort
|
2012-03-05 11:17:29 -05:00
|
|
|
assert_valid_syntax(IO::read(script), script)
|
2010-07-04 09:50:34 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2011-02-04 12:09:45 -05:00
|
|
|
|
|
|
|
def test_must_ascii_compatible
|
|
|
|
require 'tempfile'
|
|
|
|
f = Tempfile.new("must_ac_")
|
|
|
|
Encoding.list.each do |enc|
|
|
|
|
next unless enc.ascii_compatible?
|
|
|
|
make_tmpsrc(f, "# -*- coding: #{enc.name} -*-")
|
|
|
|
assert_nothing_raised(ArgumentError, enc.name) {load(f.path)}
|
|
|
|
end
|
|
|
|
Encoding.list.each do |enc|
|
|
|
|
next if enc.ascii_compatible?
|
|
|
|
make_tmpsrc(f, "# -*- coding: #{enc.name} -*-")
|
|
|
|
assert_raise(ArgumentError, enc.name) {load(f.path)}
|
|
|
|
end
|
|
|
|
f.close!
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_script_lines
|
|
|
|
require 'tempfile'
|
|
|
|
f = Tempfile.new("bug4361_")
|
|
|
|
bug4361 = '[ruby-dev:43168]'
|
|
|
|
with_script_lines do |debug_lines|
|
|
|
|
Encoding.list.each do |enc|
|
|
|
|
next unless enc.ascii_compatible?
|
|
|
|
make_tmpsrc(f, "# -*- coding: #{enc.name} -*-\n#----------------")
|
|
|
|
load(f.path)
|
|
|
|
assert_equal([f.path], debug_lines.keys)
|
|
|
|
assert_equal([enc, enc], debug_lines[f.path].map(&:encoding), bug4361)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
f.close!
|
|
|
|
end
|
|
|
|
|
2012-02-27 03:27:39 -05:00
|
|
|
def test_newline_in_block_parameters
|
|
|
|
bug = '[ruby-dev:45292]'
|
|
|
|
["", "a", "a, b"].product(["", ";x", [";", "x"]]) do |params|
|
|
|
|
params = ["|", *params, "|"].join("\n")
|
2012-03-05 11:17:29 -05:00
|
|
|
assert_valid_syntax("1.times{#{params}}", __FILE__, "#{bug} #{params.inspect}")
|
2012-02-27 03:27:39 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-03-05 11:34:21 -05:00
|
|
|
tap do |_,
|
|
|
|
bug6115 = '[ruby-dev:45308]',
|
|
|
|
blockcall = '["elem"].each_with_object [] do end',
|
|
|
|
methods = [['map', 'no'], ['inject([])', 'with']],
|
|
|
|
blocks = [['do end', 'do'], ['{}', 'brace']],
|
|
|
|
*|
|
|
|
|
[%w'. dot', %w':: colon'].product(methods, blocks) do |(c, n1), (m, n2), (b, n3)|
|
|
|
|
m = m.tr_s('()', ' ').strip if n2 == 'do'
|
|
|
|
name = "test_#{n3}_block_after_blockcall_#{n1}_#{n2}_arg"
|
|
|
|
code = "#{blockcall}#{c}#{m} #{b}"
|
|
|
|
define_method(name) {assert_valid_syntax(code, bug6115)}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-03-13 02:17:08 -04:00
|
|
|
def test_keyword_rest
|
|
|
|
bug5989 = '[ruby-core:42455]'
|
2012-03-16 04:38:13 -04:00
|
|
|
assert_valid_syntax("def kwrest_test(**a) a; end", __FILE__, bug5989)
|
|
|
|
assert_valid_syntax("def kwrest_test2(**a, &b) end", __FILE__, bug5989)
|
2012-03-13 09:00:17 -04:00
|
|
|
o = Object.new
|
|
|
|
def o.kw(**a) a end
|
2012-03-16 04:38:13 -04:00
|
|
|
assert_equal({}, o.kw, bug5989)
|
|
|
|
assert_equal({foo: 1}, o.kw(foo: 1), bug5989)
|
|
|
|
assert_equal({foo: 1, bar: 2}, o.kw(foo: 1, bar: 2), bug5989)
|
2012-06-21 04:20:51 -04:00
|
|
|
EnvUtil.under_gc_stress do
|
|
|
|
eval("def o.m(k: 0) k end")
|
|
|
|
end
|
|
|
|
assert_equal(42, o.m(k: 42), '[ruby-core:45744]')
|
2012-03-13 02:17:08 -04:00
|
|
|
end
|
|
|
|
|
2012-04-28 17:12:05 -04:00
|
|
|
def test_keyword_splat
|
|
|
|
assert_valid_syntax("foo(**h)", __FILE__)
|
|
|
|
o = Object.new
|
|
|
|
def o.kw(k1: 1, k2: 2) [k1, k2] end
|
|
|
|
h = {k1: 11, k2: 12}
|
|
|
|
assert_equal([11, 12], o.kw(**h))
|
|
|
|
assert_equal([11, 22], o.kw(k2: 22, **h))
|
|
|
|
assert_equal([11, 12], o.kw(**h, **{k2: 22}))
|
|
|
|
assert_equal([11, 22], o.kw(**{k2: 22}, **h))
|
|
|
|
h = {k3: 31}
|
|
|
|
assert_raise(ArgumentError) {o.kw(**h)}
|
|
|
|
h = {"k1"=>11, k2: 12}
|
|
|
|
assert_raise(TypeError) {o.kw(**h)}
|
|
|
|
end
|
|
|
|
|
2012-03-15 02:37:46 -04:00
|
|
|
def test_warn_grouped_expression
|
2012-07-18 10:20:09 -04:00
|
|
|
bug5214 = '[ruby-core:39050]'
|
|
|
|
assert_warn("", bug5214) do
|
2012-03-15 02:37:46 -04:00
|
|
|
assert_valid_syntax("foo \\\n(\n true)", "test") {$VERBOSE = true}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-03-16 04:42:16 -04:00
|
|
|
def test_warn_unreachable
|
|
|
|
assert_warn("test:3: warning: statement not reached\n") do
|
|
|
|
code = "loop do\n" "break\n" "foo\n" "end"
|
|
|
|
assert_valid_syntax(code, "test") {$VERBOSE = true}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-04-24 03:04:41 -04:00
|
|
|
def test_cmd_symbol_after_keyword
|
|
|
|
bug6347 = '[ruby-dev:45563]'
|
|
|
|
assert_not_label(:foo, 'if true then not_label:foo end', bug6347)
|
|
|
|
assert_not_label(:foo, 'if false; else not_label:foo end', bug6347)
|
|
|
|
assert_not_label(:foo, 'begin not_label:foo end', bug6347)
|
|
|
|
assert_not_label(:foo, 'begin ensure not_label:foo end', bug6347)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_cmd_symbol_in_string
|
|
|
|
bug6347 = '[ruby-dev:45563]'
|
|
|
|
assert_not_label(:foo, '"#{not_label:foo}"', bug6347)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_cmd_symbol_singleton_class
|
|
|
|
bug6347 = '[ruby-dev:45563]'
|
|
|
|
@not_label = self
|
|
|
|
assert_not_label(:foo, 'class << not_label:foo; end', bug6347)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_cmd_symbol_superclass
|
|
|
|
bug6347 = '[ruby-dev:45563]'
|
|
|
|
@not_label = Object
|
|
|
|
assert_not_label(:foo, 'class Foo < not_label:foo; end', bug6347)
|
|
|
|
end
|
|
|
|
|
2012-04-24 05:20:42 -04:00
|
|
|
def test_duplicated_when
|
|
|
|
w = 'warning: duplicated when clause is ignored'
|
|
|
|
assert_warn(/3: #{w}.+4: #{w}.+4: #{w}.+5: #{w}.+5: #{w}/m){
|
|
|
|
eval %q{
|
|
|
|
case 1
|
|
|
|
when 1, 1
|
|
|
|
when 1, 1
|
|
|
|
when 1, 1
|
|
|
|
end
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert_warn(/#{w}/){#/3: #{w}.+4: #{w}.+5: #{w}.+5: #{w}/m){
|
|
|
|
a = 1
|
|
|
|
eval %q{
|
|
|
|
case 1
|
|
|
|
when 1, 1
|
|
|
|
when 1, a
|
|
|
|
when 1, 1
|
|
|
|
end
|
|
|
|
}
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2012-05-02 10:21:23 -04:00
|
|
|
def test_lambda_with_space
|
|
|
|
feature6390 = '[ruby-dev:45605]'
|
|
|
|
assert_valid_syntax("-> (x, y) {}", __FILE__, feature6390)
|
|
|
|
end
|
|
|
|
|
2012-05-11 01:23:14 -04:00
|
|
|
def test_do_block_in_cmdarg_begin
|
|
|
|
bug6419 = '[ruby-dev:45631]'
|
|
|
|
assert_valid_syntax("p begin 1.times do 1 end end", __FILE__, bug6419)
|
|
|
|
end
|
|
|
|
|
2012-05-14 03:28:36 -04:00
|
|
|
def test_reserved_method_no_args
|
|
|
|
bug6403 = '[ruby-dev:45626]'
|
|
|
|
assert_valid_syntax("def self; :foo; end", __FILE__, bug6403)
|
|
|
|
end
|
|
|
|
|
2011-02-04 12:09:45 -05:00
|
|
|
private
|
|
|
|
|
2012-04-24 03:04:41 -04:00
|
|
|
def not_label(x) @result = x; @not_label ||= nil end
|
|
|
|
def assert_not_label(expected, src, message = nil)
|
|
|
|
@result = nil
|
|
|
|
assert_nothing_raised(SyntaxError, message) {eval(src)}
|
|
|
|
assert_equal(expected, @result, message)
|
|
|
|
end
|
|
|
|
|
2011-02-04 12:09:45 -05:00
|
|
|
def make_tmpsrc(f, src)
|
|
|
|
f.open
|
|
|
|
f.truncate(0)
|
|
|
|
f.puts(src)
|
|
|
|
f.close
|
|
|
|
end
|
|
|
|
|
|
|
|
def with_script_lines
|
|
|
|
script_lines = nil
|
|
|
|
debug_lines = {}
|
|
|
|
Object.class_eval do
|
|
|
|
if defined?(SCRIPT_LINES__)
|
|
|
|
script_lines = SCRIPT_LINES__
|
|
|
|
remove_const :SCRIPT_LINES__
|
|
|
|
end
|
|
|
|
const_set(:SCRIPT_LINES__, debug_lines)
|
|
|
|
end
|
|
|
|
yield debug_lines
|
|
|
|
ensure
|
|
|
|
Object.class_eval do
|
|
|
|
remove_const :SCRIPT_LINES__
|
|
|
|
const_set(:SCRIPT_LINES__, script_lines) if script_lines
|
|
|
|
end
|
|
|
|
end
|
2010-07-04 09:50:34 -04:00
|
|
|
end
|