mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
ee7f8d4805
Divide big array (or hash) literals into several blocks and concatetene them. There was a problem that a big array (hash) literal causes SystemStackError exception (stack overflow) because VM push all contents of the literal onto VM stack to make an array (or hash). To solve this issue, we make several arrays (hashes) and concatenate them to make a big array (hash) object. ?? * compile.c (iseq_compile_each, setup_args): use modified compile_array. * vm.c (m_core_hash_from_ary, m_core_hash_merge_ary, m_core_hash_merge_ptr): added for above change. * id.c (Init_id), parse.y: add core method ids. * bootstraptest/test_literal.rb: add simple tests. * bootstraptest/test_eval.rb: remove rescue clause to catch SystemStackError exception. * test/ruby/test_literal.rb: add tests to check no stack overflow. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35306 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
301 lines
9.1 KiB
Ruby
301 lines
9.1 KiB
Ruby
require 'test/unit'
|
|
require_relative 'envutil'
|
|
|
|
class TestRubyLiteral < Test::Unit::TestCase
|
|
|
|
def test_special_const
|
|
assert_equal 'true', true.inspect
|
|
assert_instance_of TrueClass, true
|
|
assert_equal 'false', false.inspect
|
|
assert_instance_of FalseClass, false
|
|
assert_equal 'nil', nil.inspect
|
|
assert_instance_of NilClass, nil
|
|
assert_equal ':sym', :sym.inspect
|
|
assert_instance_of Symbol, :sym
|
|
assert_equal '1234', 1234.inspect
|
|
assert_instance_of Fixnum, 1234
|
|
assert_equal '1234', 1_2_3_4.inspect
|
|
assert_instance_of Fixnum, 1_2_3_4
|
|
assert_equal '18', 0x12.inspect
|
|
assert_instance_of Fixnum, 0x12
|
|
assert_raise(SyntaxError) { eval("0x") }
|
|
assert_equal '15', 0o17.inspect
|
|
assert_instance_of Fixnum, 0o17
|
|
assert_raise(SyntaxError) { eval("0o") }
|
|
assert_equal '5', 0b101.inspect
|
|
assert_instance_of Fixnum, 0b101
|
|
assert_raise(SyntaxError) { eval("0b") }
|
|
assert_equal '123456789012345678901234567890', 123456789012345678901234567890.inspect
|
|
assert_instance_of Bignum, 123456789012345678901234567890
|
|
assert_instance_of Float, 1.3
|
|
assert_equal '2', eval("0x00+2").inspect
|
|
end
|
|
|
|
def test_self
|
|
assert_equal self, self
|
|
assert_instance_of TestRubyLiteral, self
|
|
assert_respond_to self, :test_self
|
|
end
|
|
|
|
def test_string
|
|
assert_instance_of String, ?a
|
|
assert_equal "a", ?a
|
|
assert_instance_of String, ?A
|
|
assert_equal "A", ?A
|
|
assert_instance_of String, ?\n
|
|
assert_equal "\n", ?\n
|
|
assert_equal " ", ?\ # space
|
|
assert_equal '', ''
|
|
assert_equal 'string', 'string'
|
|
assert_equal 'string string', 'string string'
|
|
assert_equal ' ', ' '
|
|
assert_equal ' ', " "
|
|
assert_equal "\0", "\0"
|
|
assert_equal "\1", "\1"
|
|
assert_equal "3", "\x33"
|
|
assert_equal "\n", "\n"
|
|
bug2500 = '[ruby-core:27228]'
|
|
bug5262 = '[ruby-core:39222]'
|
|
%w[c C- M-].each do |pre|
|
|
["u", %w[u{ }]].each do |open, close|
|
|
["?", ['"', '"']].each do |qopen, qclose|
|
|
str = "#{qopen}\\#{pre}\\#{open}5555#{close}#{qclose}"
|
|
assert_raise(SyntaxError, "#{bug2500} eval(#{str})") {eval(str)}
|
|
|
|
str = "#{qopen}\\#{pre}\\#{open}\u201c#{close}#{qclose}"
|
|
assert_raise(SyntaxError, "#{bug5262} eval(#{str})") {eval(str)}
|
|
|
|
str = "#{qopen}\\#{pre}\\#{open}\u201c#{close}#{qclose}".encode("euc-jp")
|
|
assert_raise(SyntaxError, "#{bug5262} eval(#{str})") {eval(str)}
|
|
|
|
str = "#{qopen}\\#{pre}\\#{open}\u201c#{close}#{qclose}".encode("iso-8859-13")
|
|
assert_raise(SyntaxError, "#{bug5262} eval(#{str})") {eval(str)}
|
|
|
|
str = "#{qopen}\\#{pre}\\#{open}\xe2\x7f#{close}#{qclose}".force_encoding("utf-8")
|
|
assert_raise(SyntaxError, "#{bug5262} eval(#{str})") {eval(str)}
|
|
end
|
|
end
|
|
end
|
|
bug6069 = '[ruby-dev:45278]'
|
|
assert_equal "\x13", "\c\x33"
|
|
assert_equal "\x13", "\C-\x33"
|
|
assert_equal "\xB3", "\M-\x33"
|
|
assert_equal "\u201c", eval(%["\\\u{201c}"]), bug5262
|
|
assert_equal "\u201c".encode("euc-jp"), eval(%["\\\u{201c}"].encode("euc-jp")), bug5262
|
|
assert_equal "\u201c".encode("iso-8859-13"), eval(%["\\\u{201c}"].encode("iso-8859-13")), bug5262
|
|
assert_equal "\\\u201c", eval(%['\\\u{201c}']), bug6069
|
|
assert_equal "\\\u201c".encode("euc-jp"), eval(%['\\\u{201c}'].encode("euc-jp")), bug6069
|
|
assert_equal "\\\u201c".encode("iso-8859-13"), eval(%['\\\u{201c}'].encode("iso-8859-13")), bug6069
|
|
assert_equal "\u201c", eval(%[?\\\u{201c}]), bug6069
|
|
assert_equal "\u201c".encode("euc-jp"), eval(%[?\\\u{201c}].encode("euc-jp")), bug6069
|
|
assert_equal "\u201c".encode("iso-8859-13"), eval(%[?\\\u{201c}].encode("iso-8859-13")), bug6069
|
|
end
|
|
|
|
def test_dstring
|
|
assert_equal '2', "#{1+1}"
|
|
assert_equal '16', "#{2 ** 4}"
|
|
s = "string"
|
|
assert_equal s, "#{s}"
|
|
a = 'Foo'
|
|
b = "#{a}" << 'Bar'
|
|
assert_equal('Foo', a, 'r3842')
|
|
assert_equal('FooBar', b, 'r3842')
|
|
end
|
|
|
|
def test_dsymbol
|
|
assert_equal :a3c, :"a#{1+2}c"
|
|
end
|
|
|
|
def test_xstring
|
|
assert_equal "foo\n", `echo foo`
|
|
s = 'foo'
|
|
assert_equal "foo\n", `echo #{s}`
|
|
end
|
|
|
|
def test_regexp
|
|
assert_instance_of Regexp, //
|
|
assert_match(//, 'a')
|
|
assert_match(//, '')
|
|
assert_instance_of Regexp, /a/
|
|
assert_match(/a/, 'a')
|
|
assert_no_match(/test/, 'tes')
|
|
re = /test/
|
|
assert_match re, 'test'
|
|
str = 'test'
|
|
assert_match re, str
|
|
assert_match(/test/, str)
|
|
assert_equal 0, (/test/ =~ 'test')
|
|
assert_equal 0, (re =~ 'test')
|
|
assert_equal 0, (/test/ =~ str)
|
|
assert_equal 0, (re =~ str)
|
|
assert_equal 0, ('test' =~ /test/)
|
|
assert_equal 0, ('test' =~ re)
|
|
assert_equal 0, (str =~ /test/)
|
|
assert_equal 0, (str =~ re)
|
|
end
|
|
|
|
def test_dregexp
|
|
assert_instance_of Regexp, /re#{'ge'}xp/
|
|
assert_equal(/regexp/, /re#{'ge'}xp/)
|
|
bug3903 = '[ruby-core:32682]'
|
|
assert_raise(SyntaxError, bug3903) {eval('/[#{"\x80"}]/')}
|
|
end
|
|
|
|
def test_array
|
|
assert_instance_of Array, []
|
|
assert_equal [], []
|
|
assert_equal 0, [].size
|
|
assert_instance_of Array, [0]
|
|
assert_equal [3], [3]
|
|
assert_equal 1, [3].size
|
|
a = [3]
|
|
assert_equal 3, a[0]
|
|
assert_instance_of Array, [1,2]
|
|
assert_equal [1,2], [1,2]
|
|
assert_instance_of Array, [1,2,3,4,5]
|
|
assert_equal [1,2,3,4,5], [1,2,3,4,5]
|
|
assert_equal 5, [1,2,3,4,5].size
|
|
a = [1,2]
|
|
assert_equal 1, a[0]
|
|
assert_equal 2, a[1]
|
|
a = [1 + 2, 3 + 4, 5 + 6]
|
|
assert_instance_of Array, a
|
|
assert_equal [3, 7, 11], a
|
|
assert_equal 7, a[1]
|
|
assert_equal 1, ([0][0] += 1)
|
|
assert_equal 1, ([2][0] -= 1)
|
|
a = [obj = Object.new]
|
|
assert_instance_of Array, a
|
|
assert_equal 1, a.size
|
|
assert_equal obj, a[0]
|
|
a = [1,2,3]
|
|
a[1] = 5
|
|
assert_equal 5, a[1]
|
|
end
|
|
|
|
def test_hash
|
|
assert_instance_of Hash, {}
|
|
assert_equal({}, {})
|
|
assert_instance_of Hash, {1 => 2}
|
|
assert_equal({1 => 2}, {1 => 2})
|
|
h = {1 => 2}
|
|
assert_equal 2, h[1]
|
|
h = {"string" => "literal", "goto" => "hell"}
|
|
assert_equal h, h
|
|
assert_equal 2, h.size
|
|
assert_equal h, h
|
|
assert_equal "literal", h["string"]
|
|
end
|
|
|
|
def test_big_array_and_hash_literal
|
|
assert_normal_exit %q{x = nil; raise if eval("[#{(1..1_000_000).map{'x'}.join(", ")}]").size != 1_000_000}, "", timeout: 300
|
|
assert_normal_exit %q{x = nil; raise if eval("[#{(1..1_000_000).to_a.join(", ")}]").size != 1_000_000}, "", timeout: 300
|
|
assert_normal_exit %q{x = nil; raise if eval("{#{(1..1_000_000).map{|n| "#{n} => x"}.join(', ')}}").size != 1_000_000}, "", timeout: 300
|
|
assert_normal_exit %q{x = nil; raise if eval("{#{(1..1_000_000).map{|n| "#{n} => #{n}"}.join(', ')}}").size != 1_000_000}, "", timeout: 300
|
|
end
|
|
|
|
def test_range
|
|
assert_instance_of Range, (1..2)
|
|
assert_equal(1..2, 1..2)
|
|
r = 1..2
|
|
assert_equal 1, r.begin
|
|
assert_equal 2, r.end
|
|
assert_equal false, r.exclude_end?
|
|
assert_instance_of Range, (1...3)
|
|
assert_equal(1...3, 1...3)
|
|
r = 1...3
|
|
assert_equal 1, r.begin
|
|
assert_equal 3, r.end
|
|
assert_equal true, r.exclude_end?
|
|
r = 1+2 .. 3+4
|
|
assert_instance_of Range, r
|
|
assert_equal 3, r.begin
|
|
assert_equal 7, r.end
|
|
assert_equal false, r.exclude_end?
|
|
r = 1+2 ... 3+4
|
|
assert_instance_of Range, r
|
|
assert_equal 3, r.begin
|
|
assert_equal 7, r.end
|
|
assert_equal true, r.exclude_end?
|
|
assert_instance_of Range, 'a'..'c'
|
|
r = 'a'..'c'
|
|
assert_equal 'a', r.begin
|
|
assert_equal 'c', r.end
|
|
end
|
|
|
|
def test__FILE__
|
|
assert_instance_of String, __FILE__
|
|
assert_equal __FILE__, __FILE__
|
|
assert_equal 'test_literal.rb', File.basename(__FILE__)
|
|
end
|
|
|
|
def test__LINE__
|
|
assert_instance_of Fixnum, __LINE__
|
|
assert_equal __LINE__, __LINE__
|
|
end
|
|
|
|
def test_integer
|
|
head = ['', '0x', '0o', '0b', '0d', '-', '+']
|
|
chars = ['0', '1', '_', '9', 'f']
|
|
head.each {|h|
|
|
4.times {|len|
|
|
a = [h]
|
|
len.times { a = a.product(chars).map {|x| x.join('') } }
|
|
a.each {|s|
|
|
next if s.empty?
|
|
begin
|
|
r1 = Integer(s)
|
|
rescue ArgumentError
|
|
r1 = :err
|
|
end
|
|
begin
|
|
r2 = eval(s)
|
|
rescue NameError, SyntaxError
|
|
r2 = :err
|
|
end
|
|
assert_equal(r1, r2, "Integer(#{s.inspect}) != eval(#{s.inspect})")
|
|
}
|
|
}
|
|
}
|
|
bug2407 = '[ruby-dev:39798]'
|
|
head.each {|h|
|
|
if /^0/ =~ h
|
|
begin
|
|
eval("#{h}_")
|
|
rescue SyntaxError => e
|
|
assert_match(/numeric literal without digits\Z/, e.message, bug2407)
|
|
end
|
|
end
|
|
}
|
|
end
|
|
|
|
def test_float
|
|
head = ['', '-', '+']
|
|
chars = ['0', '1', '_', '9', 'f', '.']
|
|
head.each {|h|
|
|
6.times {|len|
|
|
a = [h]
|
|
len.times { a = a.product(chars).map {|x| x.join('') } }
|
|
a.each {|s|
|
|
next if s.empty?
|
|
next if /\.\z/ =~ s
|
|
next if /\A[-+]?\./ =~ s
|
|
next if /\A[-+]?0/ =~ s
|
|
begin
|
|
r1 = Float(s)
|
|
rescue ArgumentError
|
|
r1 = :err
|
|
end
|
|
begin
|
|
r2 = eval(s)
|
|
rescue NameError, SyntaxError
|
|
r2 = :err
|
|
end
|
|
r2 = :err if Range === r2
|
|
assert_equal(r1, r2, "Float(#{s.inspect}) != eval(#{s.inspect})")
|
|
}
|
|
}
|
|
}
|
|
end
|
|
|
|
end
|