From fcbf63e62c627deae76c1b8cb8c0876c536ed811 Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Mon, 16 Mar 2020 18:49:26 +0900 Subject: Fresh start --- jni/ruby/bootstraptest/pending.rb | 39 + jni/ruby/bootstraptest/runner.rb | 505 ++++++++++ jni/ruby/bootstraptest/test_attr.rb | 36 + jni/ruby/bootstraptest/test_autoload.rb | 70 ++ jni/ruby/bootstraptest/test_block.rb | 613 +++++++++++++ jni/ruby/bootstraptest/test_class.rb | 169 ++++ jni/ruby/bootstraptest/test_eval.rb | 324 +++++++ jni/ruby/bootstraptest/test_exception.rb | 432 +++++++++ jni/ruby/bootstraptest/test_finalizer.rb | 8 + jni/ruby/bootstraptest/test_flip.rb | 1 + jni/ruby/bootstraptest/test_flow.rb | 591 ++++++++++++ jni/ruby/bootstraptest/test_fork.rb | 75 ++ jni/ruby/bootstraptest/test_gc.rb | 34 + jni/ruby/bootstraptest/test_io.rb | 112 +++ jni/ruby/bootstraptest/test_jump.rb | 308 +++++++ jni/ruby/bootstraptest/test_literal.rb | 231 +++++ jni/ruby/bootstraptest/test_literal_suffix.rb | 54 ++ jni/ruby/bootstraptest/test_load.rb | 27 + jni/ruby/bootstraptest/test_marshal.rb | 5 + jni/ruby/bootstraptest/test_massign.rb | 183 ++++ jni/ruby/bootstraptest/test_method.rb | 1220 +++++++++++++++++++++++++ jni/ruby/bootstraptest/test_objectspace.rb | 46 + jni/ruby/bootstraptest/test_proc.rb | 483 ++++++++++ jni/ruby/bootstraptest/test_string.rb | 3 + jni/ruby/bootstraptest/test_struct.rb | 5 + jni/ruby/bootstraptest/test_syntax.rb | 902 ++++++++++++++++++ jni/ruby/bootstraptest/test_thread.rb | 476 ++++++++++ 27 files changed, 6952 insertions(+) create mode 100644 jni/ruby/bootstraptest/pending.rb create mode 100755 jni/ruby/bootstraptest/runner.rb create mode 100644 jni/ruby/bootstraptest/test_attr.rb create mode 100644 jni/ruby/bootstraptest/test_autoload.rb create mode 100644 jni/ruby/bootstraptest/test_block.rb create mode 100644 jni/ruby/bootstraptest/test_class.rb create mode 100644 jni/ruby/bootstraptest/test_eval.rb create mode 100644 jni/ruby/bootstraptest/test_exception.rb create mode 100644 jni/ruby/bootstraptest/test_finalizer.rb create mode 100644 jni/ruby/bootstraptest/test_flip.rb create mode 100644 jni/ruby/bootstraptest/test_flow.rb create mode 100644 jni/ruby/bootstraptest/test_fork.rb create mode 100644 jni/ruby/bootstraptest/test_gc.rb create mode 100644 jni/ruby/bootstraptest/test_io.rb create mode 100644 jni/ruby/bootstraptest/test_jump.rb create mode 100644 jni/ruby/bootstraptest/test_literal.rb create mode 100644 jni/ruby/bootstraptest/test_literal_suffix.rb create mode 100644 jni/ruby/bootstraptest/test_load.rb create mode 100644 jni/ruby/bootstraptest/test_marshal.rb create mode 100644 jni/ruby/bootstraptest/test_massign.rb create mode 100644 jni/ruby/bootstraptest/test_method.rb create mode 100644 jni/ruby/bootstraptest/test_objectspace.rb create mode 100644 jni/ruby/bootstraptest/test_proc.rb create mode 100644 jni/ruby/bootstraptest/test_string.rb create mode 100644 jni/ruby/bootstraptest/test_struct.rb create mode 100644 jni/ruby/bootstraptest/test_syntax.rb create mode 100644 jni/ruby/bootstraptest/test_thread.rb (limited to 'jni/ruby/bootstraptest') diff --git a/jni/ruby/bootstraptest/pending.rb b/jni/ruby/bootstraptest/pending.rb new file mode 100644 index 0000000..744c0ad --- /dev/null +++ b/jni/ruby/bootstraptest/pending.rb @@ -0,0 +1,39 @@ +assert_equal 'A', %q{ + class A + @@a = 'A' + def a=(x) + @@a = x + end + def a + @@a + end + end + + B = A.dup + B.new.a = 'B' + A.new.a +}, '[ruby-core:17019]' + +assert_equal 'ok', %q{ + def m + lambda{ + proc{ + return :ng1 + } + }.call.call + :ng2 + end + + begin + m() + rescue LocalJumpError + :ok + end +} + +assert_normal_exit %q{ + r = Range.allocate + def r.<=>(o) true end + r.instance_eval { initialize r, r } + r.inspect +} diff --git a/jni/ruby/bootstraptest/runner.rb b/jni/ruby/bootstraptest/runner.rb new file mode 100755 index 0000000..a5c9b23 --- /dev/null +++ b/jni/ruby/bootstraptest/runner.rb @@ -0,0 +1,505 @@ +"exec" "${RUBY-ruby}" "-x" "$0" "$@" || true # -*- mode: ruby; coding: utf-8 -*- +#!./ruby +# $Id: runner.rb 46486 2014-06-21 23:43:50Z akr $ + +# NOTE: +# Never use optparse in this file. +# Never use test/unit in this file. +# Never use Ruby extensions in this file. + +begin + require 'fileutils' + require 'tmpdir' +rescue LoadError + $:.unshift File.join(File.dirname(__FILE__), '../lib') + retry +end + +if !Dir.respond_to?(:mktmpdir) + # copied from lib/tmpdir.rb + def Dir.mktmpdir(prefix_suffix=nil, tmpdir=nil) + case prefix_suffix + when nil + prefix = "d" + suffix = "" + when String + prefix = prefix_suffix + suffix = "" + when Array + prefix = prefix_suffix[0] + suffix = prefix_suffix[1] + else + raise ArgumentError, "unexpected prefix_suffix: #{prefix_suffix.inspect}" + end + tmpdir ||= Dir.tmpdir + t = Time.now.strftime("%Y%m%d") + n = nil + begin + path = "#{tmpdir}/#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}" + path << "-#{n}" if n + path << suffix + Dir.mkdir(path, 0700) + rescue Errno::EEXIST + n ||= 0 + n += 1 + retry + end + + if block_given? + begin + yield path + ensure + FileUtils.remove_entry_secure path + end + else + path + end + end +end + +def main + @ruby = File.expand_path('miniruby') + @verbose = false + $stress = false + @color = nil + @tty = nil + @quiet = false + dir = nil + quiet = false + tests = nil + ARGV.delete_if {|arg| + case arg + when /\A--ruby=(.*)/ + @ruby = $1 + @ruby.gsub!(/^([^ ]*)/){File.expand_path($1)} + @ruby.gsub!(/(\s+-I\s*)((?!(?:\.\/)*-(?:\s|\z))\S+)/){$1+File.expand_path($2)} + @ruby.gsub!(/(\s+-r\s*)(\.\.?\/\S+)/){$1+File.expand_path($2)} + true + when /\A--sets=(.*)/ + tests = Dir.glob("#{File.dirname($0)}/test_{#{$1}}*.rb").sort + puts tests.map {|path| File.basename(path) }.inspect + true + when /\A--dir=(.*)/ + dir = $1 + true + when /\A(--stress|-s)/ + $stress = true + when /\A--color(?:=(?:always|(auto)|(never)|(.*)))?\z/ + warn "unknown --color argument: #$3" if $3 + @color = $1 ? nil : !$2 + true + when /\A--tty(=(?:yes|(no)|(.*)))?\z/ + warn "unknown --tty argument: #$3" if $3 + @tty = !$1 || !$2 + true + when /\A(-q|--q(uiet))\z/ + quiet = true + @quiet = true + true + when /\A(-v|--v(erbose))\z/ + @verbose = true + when /\A(-h|--h(elp)?)\z/ + puts(<<-End) +Usage: #{File.basename($0, '.*')} --ruby=PATH [--sets=NAME,NAME,...] + --sets=NAME,NAME,... Name of test sets. + --dir=DIRECTORY Working directory. + default: /tmp/bootstraptestXXXXX.tmpwd + --color[=WHEN] Colorize the output. WHEN defaults to 'always' + or can be 'never' or 'auto'. + -s, --stress stress test. + -v, --verbose Output test name before exec. + -q, --quiet Don\'t print header message. + -h, --help Print this message and quit. +End + exit true + when /\A-j/ + true + else + false + end + } + if tests and not ARGV.empty? + $stderr.puts "--tests and arguments are exclusive" + exit false + end + tests ||= ARGV + tests = Dir.glob("#{File.dirname($0)}/test_*.rb").sort if tests.empty? + pathes = tests.map {|path| File.expand_path(path) } + + @progress = %w[- \\ | /] + @progress_bs = "\b" * @progress[0].size + @tty = $stderr.tty? if @tty.nil? + case @color + when nil + @color = @tty && /dumb/ !~ ENV["TERM"] + end + @tty &&= !@verbose + if @color + # dircolors-like style + colors = (colors = ENV['TEST_COLORS']) ? Hash[colors.scan(/(\w+)=([^:]*)/)] : {} + @passed = "\e[#{colors["pass"] || "32"}m" + @failed = "\e[#{colors["fail"] || "31"}m" + @reset = "\e[m" + else + @passed = @failed = @reset = "" + end + unless quiet + puts Time.now + if defined?(RUBY_DESCRIPTION) + puts "Driver is #{RUBY_DESCRIPTION}" + elsif defined?(RUBY_PATCHLEVEL) + puts "Driver is ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}#{RUBY_PLATFORM}) [#{RUBY_PLATFORM}]" + else + puts "Driver is ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]" + end + puts "Target is #{`#{@ruby} -v`.chomp}" + puts + $stdout.flush + end + + in_temporary_working_directory(dir) { + exec_test pathes + } +end + +def erase(e = true) + if e and @columns > 0 and !@verbose + "\r#{" "*@columns}\r" + else + "" + end +end + +def exec_test(pathes) + @count = 0 + @error = 0 + @errbuf = [] + @location = nil + @columns = 0 + @width = pathes.map {|path| File.basename(path).size}.max + 2 + pathes.each do |path| + @basename = File.basename(path) + $stderr.printf("%s%-*s ", erase(@quiet), @width, @basename) + $stderr.flush + @columns = @width + 1 + $stderr.puts if @verbose + count = @count + error = @error + load File.expand_path(path) + if @tty + if @error == error + msg = "PASS #{@count-count}" + @columns += msg.size - 1 + $stderr.print "#{@progress_bs}#{@passed}#{msg}#{@reset}" + else + msg = "FAIL #{@error-error}/#{@count-count}" + $stderr.print "#{@progress_bs}#{@failed}#{msg}#{@reset}" + @columns = 0 + end + end + $stderr.puts unless @quiet and @tty and @error == error + end + $stderr.print(erase) if @quiet + if @error == 0 + if @count == 0 + $stderr.puts "No tests, no problem" + else + $stderr.puts "#{@passed}PASS#{@reset} all #{@count} tests" + end + exit true + else + @errbuf.each do |msg| + $stderr.puts msg + end + $stderr.puts "#{@failed}FAIL#{@reset} #{@error}/#{@count} tests failed" + exit false + end +end + +def show_progress(message = '') + if @verbose + $stderr.print "\##{@count} #{@location} " + elsif @tty + $stderr.print "#{@progress_bs}#{@progress[@count % @progress.size]}" + end + t = Time.now if @verbose + faildesc, errout = with_stderr {yield} + t = Time.now - t if @verbose + if !faildesc + if @tty + $stderr.print "#{@progress_bs}#{@progress[@count % @progress.size]}" + elsif @verbose + $stderr.printf(". %.3f\n", t) + else + $stderr.print '.' + end + else + $stderr.print "#{@failed}F" + $stderr.printf(" %.3f", t) if @verbose + $stderr.print "#{@reset}" + $stderr.puts if @verbose + error faildesc, message + unless errout.empty? + $stderr.print "#{@failed}stderr output is not empty#{@reset}\n", adjust_indent(errout) + end + if @tty and !@verbose + $stderr.printf("%-*s%s", @width, @basename, @progress[@count % @progress.size]) + end + end +rescue Interrupt + raise Interrupt +rescue Exception => err + $stderr.print 'E' + $stderr.puts if @verbose + error err.message, message +end + +# NativeClient is special. The binary is cross-compiled. But runs on the build environment. +# So RUBY_PLATFORM in this process is not useful to detect it. +def nacl? + @ruby and File.basename(@ruby.split(/\s/).first)['sel_ldr'] +end + +def assert_check(testsrc, message = '', opt = '') + show_progress(message) { + result = get_result_string(testsrc, opt) + check_coredump + yield(result) + } +end + +def assert_equal(expected, testsrc, message = '') + newtest + assert_check(testsrc, message) {|result| + if expected == result + nil + else + desc = "#{result.inspect} (expected #{expected.inspect})" + pretty(testsrc, desc, result) + end + } +end + +def assert_match(expected_pattern, testsrc, message = '') + newtest + assert_check(testsrc, message) {|result| + if expected_pattern =~ result + nil + else + desc = "#{expected_pattern.inspect} expected to be =~\n#{result.inspect}" + pretty(testsrc, desc, result) + end + } +end + +def assert_not_match(unexpected_pattern, testsrc, message = '') + newtest + assert_check(testsrc, message) {|result| + if unexpected_pattern !~ result + nil + else + desc = "#{unexpected_pattern.inspect} expected to be !~\n#{result.inspect}" + pretty(testsrc, desc, result) + end + } +end + +def assert_valid_syntax(testsrc, message = '') + newtest + assert_check(testsrc, message, '-c') {|result| + result if /Syntax OK/ !~ result + } +end + +def assert_normal_exit(testsrc, *rest) + newtest + opt = {} + opt = rest.pop if Hash === rest.last + message, ignore_signals = rest + message ||= '' + timeout = opt[:timeout] + show_progress(message) { + faildesc = nil + filename = make_srcfile(testsrc) + old_stderr = $stderr.dup + timeout_signaled = false + begin + $stderr.reopen("assert_normal_exit.log", "w") + io = IO.popen("#{@ruby} -W0 #{filename}") + pid = io.pid + th = Thread.new { + io.read + io.close + $? + } + if !th.join(timeout) + Process.kill :KILL, pid + timeout_signaled = true + end + status = th.value + ensure + $stderr.reopen(old_stderr) + old_stderr.close + end + if status && status.signaled? + signo = status.termsig + signame = Signal.list.invert[signo] + unless ignore_signals and ignore_signals.include?(signame) + sigdesc = "signal #{signo}" + if signame + sigdesc = "SIG#{signame} (#{sigdesc})" + end + if timeout_signaled + sigdesc << " (timeout)" + end + faildesc = pretty(testsrc, "killed by #{sigdesc}", nil) + stderr_log = File.read("assert_normal_exit.log") + if !stderr_log.empty? + faildesc << "\n" if /\n\z/ !~ faildesc + stderr_log << "\n" if /\n\z/ !~ stderr_log + stderr_log.gsub!(/^.*\n/) { '| ' + $& } + faildesc << stderr_log + end + end + end + faildesc + } +end + +def assert_finish(timeout_seconds, testsrc, message = '') + newtest + show_progress(message) { + faildesc = nil + filename = make_srcfile(testsrc) + io = IO.popen("#{@ruby} -W0 #{filename}") + pid = io.pid + waited = false + tlimit = Time.now + timeout_seconds + while Time.now < tlimit + if Process.waitpid pid, Process::WNOHANG + waited = true + break + end + sleep 0.1 + end + if !waited + Process.kill(:KILL, pid) + Process.waitpid pid + faildesc = pretty(testsrc, "not finished in #{timeout_seconds} seconds", nil) + end + io.close + faildesc + } +end + +def flunk(message = '') + newtest + show_progress('') { message } +end + +def pretty(src, desc, result) + src = src.sub(/\A.*\n/, '') + (/\n/ =~ src ? "\n#{adjust_indent(src)}" : src) + " #=> #{desc}" +end + +INDENT = 27 + +def adjust_indent(src) + untabify(src).gsub(/^ {#{INDENT}}/o, '').gsub(/^/, ' ').sub(/\s*\z/, "\n") +end + +def untabify(str) + str.gsub(/^\t+/) {' ' * (8 * $&.size) } +end + +def make_srcfile(src) + filename = 'bootstraptest.tmp.rb' + File.open(filename, 'w') {|f| + f.puts "GC.stress = true" if $stress + f.puts "print(begin; #{src}; end)" + } + filename +end + +def get_result_string(src, opt = '') + if @ruby + filename = make_srcfile(src) + begin + `#{@ruby} -W0 #{opt} #{filename}` + ensure + raise Interrupt if $? and $?.signaled? && $?.termsig == Signal.list["INT"] + raise CoreDumpError, "core dumped" if $? and $?.coredump? + end + else + eval(src).to_s + end +end + +def with_stderr + out = err = nil + begin + r, w = IO.pipe + stderr = $stderr.dup + $stderr.reopen(w) + w.close + reader = Thread.start {r.read} + begin + out = yield + ensure + $stderr.reopen(stderr) + err = reader.value + end + ensure + w.close rescue nil + r.close rescue nil + end + return out, err +end + +def newtest + @location = File.basename(caller(2).first) + @count += 1 + cleanup_coredump +end + +def error(msg, additional_message) + msg = "#{@failed}\##{@count} #{@location}#{@reset}: #{msg} #{additional_message}" + if @tty + $stderr.puts "#{erase}#{msg}" + else + @errbuf.push msg + end + @error += 1 +end + +def in_temporary_working_directory(dir) + if dir + Dir.mkdir dir + Dir.chdir(dir) { + yield + } + else + Dir.mktmpdir(["bootstraptest", ".tmpwd"]) {|d| + Dir.chdir(d) { + yield + } + } + end +end + +def cleanup_coredump + FileUtils.rm_f 'core' + FileUtils.rm_f Dir.glob('core.*') + FileUtils.rm_f @ruby+'.stackdump' if @ruby +end + +class CoreDumpError < StandardError; end + +def check_coredump + if File.file?('core') or not Dir.glob('core.*').empty? or + (@ruby and File.exist?(@ruby+'.stackdump')) + raise CoreDumpError, "core dumped" + end +end + +main diff --git a/jni/ruby/bootstraptest/test_attr.rb b/jni/ruby/bootstraptest/test_attr.rb new file mode 100644 index 0000000..721a847 --- /dev/null +++ b/jni/ruby/bootstraptest/test_attr.rb @@ -0,0 +1,36 @@ +assert_equal 'ok', %q{ + module M + class A + class << self + attr_accessor :at + def workflow_rule + yield self + end + + def eval_str(str) + eval(str) + end + end + end + end + begin + M::A.eval_str(<<-END) + workflow_rule do |r| + r.at 1 + end + END + rescue ArgumentError => e + print "ok" + end +}, '[ruby-core:14641]' + +assert_equal %{ok}, %{ + class A + attr :m + end + begin + A.new.m(3) + rescue ArgumentError => e + print "ok" + end +}, '[ruby-core:15120]' diff --git a/jni/ruby/bootstraptest/test_autoload.rb b/jni/ruby/bootstraptest/test_autoload.rb new file mode 100644 index 0000000..a9f8e6d --- /dev/null +++ b/jni/ruby/bootstraptest/test_autoload.rb @@ -0,0 +1,70 @@ +assert_equal 'ok', %q{ + File.unlink('zzz.rb') if File.file?('zzz.rb') + instance_eval do + autoload :ZZZ, './zzz.rb' + begin + ZZZ + rescue LoadError + :ok + end + end +}, '[ruby-dev:43816]' + +assert_equal 'ok', %q{ + open('zzz.rb', 'w') {|f| f.puts '' } + instance_eval do + autoload :ZZZ, './zzz.rb' + begin + ZZZ + rescue NameError + :ok + end + end +}, '[ruby-dev:43816]' + +assert_equal 'ok', %q{ + open('zzz.rb', 'w') {|f| f.puts 'class ZZZ; def self.ok;:ok;end;end'} + instance_eval do + autoload :ZZZ, './zzz.rb' + ZZZ.ok + end +}, '[ruby-dev:43816]' + +assert_equal 'ok', %q{ + open("zzz.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"} + autoload :ZZZ, "./zzz.rb" + ZZZ.ok +} + +assert_equal 'ok', %q{ + open("zzz.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"} + autoload :ZZZ, "./zzz.rb" + require "./zzz.rb" + ZZZ.ok +} + +assert_equal 'okok', %q{ + open("zzz.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"} + autoload :ZZZ, "./zzz.rb" + t1 = Thread.new {ZZZ.ok} + t2 = Thread.new {ZZZ.ok} + [t1.value, t2.value].join +} + +assert_finish 5, %q{ + autoload :ZZZ, File.expand_path(__FILE__) + begin + ZZZ + rescue NameError + end +}, '[ruby-core:21696]' + +assert_equal 'A::C', %q{ + open("zzz.rb", "w") {} + class A + autoload :C, "./zzz" + class C + end + C + end +} diff --git a/jni/ruby/bootstraptest/test_block.rb b/jni/ruby/bootstraptest/test_block.rb new file mode 100644 index 0000000..cdc5960 --- /dev/null +++ b/jni/ruby/bootstraptest/test_block.rb @@ -0,0 +1,613 @@ +assert_equal %q{1}, %q{ + 1.times{ + begin + a = 1 + ensure + foo = nil + end + } +} +assert_equal %q{2}, %q{ + [1,2,3].find{|x| x == 2} +} +assert_equal %q{2}, %q{ + class E + include Enumerable + def each(&block) + [1, 2, 3].each(&block) + end + end + E.new.find {|x| x == 2 } +} +assert_equal %q{6}, %q{ + sum = 0 + for x in [1, 2, 3] + sum += x + end + sum +} +assert_equal %q{15}, %q{ + sum = 0 + for x in (1..5) + sum += x + end + sum +} +assert_equal %q{0}, %q{ + sum = 0 + for x in [] + sum += x + end + sum +} +assert_equal %q{1}, %q{ + ans = [] + 1.times{ + for n in 1..3 + a = n + ans << a + end + } +} +assert_equal %q{1..3}, %q{ + ans = [] + for m in 1..3 + for n in 1..3 + a = [m, n] + ans << a + end + end +} +assert_equal %q{[1, 2, 3]}, %q{ + (1..3).to_a +} +assert_equal %q{[4, 8, 12]}, %q{ + (1..3).map{|e| + e * 4 + } +} +assert_equal %q{[1, 2, 3]}, %q{ + class C + include Enumerable + def each + [1,2,3].each{|e| + yield e + } + end + end + + C.new.to_a +} +assert_equal %q{[4, 5, 6]}, %q{ + class C + include Enumerable + def each + [1,2,3].each{|e| + yield e + } + end + end + + C.new.map{|e| + e + 3 + } +} +assert_equal %q{100}, %q{ + def m + yield + end + def n + yield + end + + m{ + n{ + 100 + } + } +} +assert_equal %q{20}, %q{ + def m + yield 1 + end + + m{|ib| + m{|jb| + i = 20 + } + } +} +assert_equal %q{2}, %q{ + def m + yield 1 + end + + m{|ib| + m{|jb| + ib = 20 + kb = 2 + } + } +} +assert_equal %q{3}, %q{ + def iter1 + iter2{ + yield + } + end + + def iter2 + yield + end + + iter1{ + jb = 2 + iter1{ + jb = 3 + } + jb + } +} +assert_equal %q{2}, %q{ + def iter1 + iter2{ + yield + } + end + + def iter2 + yield + end + + iter1{ + jb = 2 + iter1{ + jb + } + jb + } +} +assert_equal %q{2}, %q{ + def m + yield 1 + end + m{|ib| + ib*2 + } +} +assert_equal %q{92580}, %q{ + def m + yield 12345, 67890 + end + m{|ib,jb| + ib*2+jb + } +} +assert_equal %q{[10, nil]}, %q{ + def iter + yield 10 + end + + a = nil + [iter{|a| + a + }, a] +} +assert_equal %q{21}, %q{ + def iter + yield 10 + end + + iter{|a| + iter{|a| + a + 1 + } + a + } +} +assert_equal %q{[10, 20, 30, 40, nil, nil, nil, nil]}, %q{ + def iter + yield 10, 20, 30, 40 + end + + a = b = c = d = nil + iter{|a, b, c, d| + [a, b, c, d] + } + [a, b, c, d] +} +assert_equal %q{[10, 20, 30, 40, nil, nil]}, %q{ + def iter + yield 10, 20, 30, 40 + end + + a = b = nil + iter{|a, b, c, d| + [a, b, c, d] + } + [a, b] +} +assert_equal %q{[1]}, %q{ + $a = [] + + def iter + yield 1 + end + + def m + x = iter{|x| + $a << x + y = 0 + } + end + m + $a +} +assert_equal %q{[1, [2]]}, %q{ + def iter + yield 1, 2 + end + + iter{|a, *b| + [a, b] + } +} +assert_equal %q{[[1, 2]]}, %q{ + def iter + yield 1, 2 + end + + iter{|*a| + [a] + } +} +assert_equal %q{[1, 2, []]}, %q{ + def iter + yield 1, 2 + end + + iter{|a, b, *c| + [a, b, c] + } +} +assert_equal %q{[1, 2, nil, []]}, %q{ + def iter + yield 1, 2 + end + + iter{|a, b, c, *d| + [a, b, c, d] + } +} +assert_equal %q{1}, %q{ + def m + yield + end + m{ + 1 + } +} +assert_equal %q{15129}, %q{ + def m + yield 123 + end + m{|ib| + m{|jb| + ib*jb + } + } +} +assert_equal %q{2}, %q{ + def m a + yield a + end + m(1){|ib| + m(2){|jb| + ib*jb + } + } +} +assert_equal %q{9}, %q{ + sum = 0 + 3.times{|ib| + 2.times{|jb| + sum += ib + jb + }} + sum +} +assert_equal %q{10}, %q{ + 3.times{|bl| + break 10 + } +} +assert_equal %q{[1, 2]}, %q{ + def iter + yield 1,2,3 + end + + iter{|i, j| + [i, j] + } +} +assert_equal %q{[1, nil]}, %q{ + def iter + yield 1 + end + + iter{|i, j| + [i, j] + } +} + +assert_equal '0', %q{ +def m() +end +m {|(v0,*,(*)),|} +m {|(*v0,(*)),|} +m {|(v0,*v1,(*)),|} +m {|((v0,*v1,v2)),|} +m {|(v0,*v1,v2),|} +m {|(v0,*v1,(v2)),|} +m {|((*),*v0,v1),|} +m {|((v0),*v1,v2),|} +m {|(v0,v1,*v2,v3),|} +m {|v0,(v1,*v2,v3),|} +m {|(v0,*v1,v2),v3,|} +m {|(v0,*v1,v2)|} +m {|(v0,*v1,v2),&v3|} +m {|(v0,*v1,v2),*|} +m {|(v0,*v1,v2),*,&v3|} +m {|*,(v0,*v1,v2)|} +m {|*,(v0,*v1,v2),&v3|} +m {|v0,*,(v1,*v2,v3)|} +m {|v0,*,(v1,*v2,v3),&v4|} +m {|(v0,*v1,v2),*,v3|} +m {|(v0,*v1,v2),*,v3,&v4|} +m {|(v0, *v1, v2)|} +m {|(*,v)|} +0 +}, "block parameter (shouldn't SEGV: [ruby-dev:31143])" + +assert_equal 'nil', %q{ + def m + yield + end + m{|&b| b}.inspect +}, '[ruby-dev:31147]' + +assert_equal 'nil', %q{ + def m() + yield + end + m {|(v,(*))|}.inspect +}, '[ruby-dev:31160]' + +assert_equal 'nil', %q{ + def m() + yield + end + m {|(*,a,b)|}.inspect +}, '[ruby-dev:31153]' + +assert_equal 'nil', %q{ + def m() + yield + end + m {|((*))|}.inspect +} + +assert_equal %q{[1, 1, [1, nil], [1, nil], [1, nil], [1, nil], [1, 1], 1, [1, nil], [1, nil], [1, nil], [1, nil], [[1, 1], [1, 1]], [1, 1], [1, 1], [1, 1], [1, nil], [1, nil], [[[1, 1], [1, 1]], [[1, 1], [1, 1]]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [[1, 1], [1, 1]], [1, 1], [1, 1], [[[[1, 1], [1, 1]], [[1, 1], [1, 1]]], [[[1, 1], [1, 1]], [[1, 1], [1, 1]]]], [[[1, 1], [1, 1]], [[1, 1], [1, 1]]], [[[1, 1], [1, 1]], [[1, 1], [1, 1]]], [[[1, 1], [1, 1]], [[1, 1], [1, 1]]], [[1, 1], [1, 1]], [[1, 1], [1, 1]]]}, %q{ +def m(ary = []) + yield(ary) +end + +$ans = [] +o = 1 +5.times{ + v,(*) = o; $ans << o + m(o){|(v,(*))| $ans << v} + ((x, y)) = o; $ans << [x, y] + m(o){|((x, y))| $ans << [x, y]} + (((x, y))) = o; $ans << [x, y] + m(o){|(((x, y)))| $ans << [x, y]} + o = [o, o] +}; $ans +} + +assert_equal '0', %q{ + def m() + yield [0] + end + m {|*,v| v}.inspect +}, '[ruby-dev:31437]' +assert_equal '[0]', %q{ + def m + yield [0] + end + m{|v, &b| v}.inspect +}, '[ruby-dev:31440]' +assert_equal 'ok', %q{ + begin + lambda{|a|}.call(1, 2) + rescue ArgumentError + :ok + else + :ng + end +}, '[ruby-dev:31464]' +assert_equal 'ok', %q{ + begin + lambda{|&b|}.call(3) + rescue ArgumentError + :ok + else + :ng + end +}, '[ruby-dev:31472]' +assert_equal 'ok', %q{ + class C + def each + yield [1,2] + yield 1,2 + end + end + vs1 = [] + C.new.each {|*v| vs1 << v } + vs2 = [] + C.new.to_enum.each {|*v| vs2 << v } + vs1 == vs2 ? :ok : :ng +}, '[ruby-dev:32329]' + +assert_normal_exit %q{ + e = [1,2,3].each + 10000.times { + e = [e].each + } + Thread.new { GC.start }.join +}, '[ruby-dev:32604]' + + +assert_equal '[nil, []]', %q{ + def m() yield nil,[] end + l = lambda {|*v| v} + GC.stress=true + r = m(&l) + GC.stress=false + r.inspect +}, '[ruby-dev:32567]' + +assert_equal NilClass.to_s, %q{ + r = false; 1.times{|&b| r = b}; r.class +} + +assert_equal 'ok', %q{ + class C + define_method(:foo) do |arg, &block| + if block then block.call else arg end + end + end + C.new.foo("ng") {"ok"} +}, '[ruby-talk:266422]' + +assert_equal 'ok', %q{ + class C + define_method(:xyz) do |o, k, &block| + block.call(o, k) + end + end + C.new.xyz("o","k") {|o, k| o+k} +}, '[ruby-core:20544]' + +assert_equal 'ok', %q{ + class C + define_method(:xyz) do |*args, &block| + block.call(*args) + end + end + C.new.xyz("o","k") {|*args| args.join("")} +}, '[ruby-core:20544]' + +assert_equal 'ok', %q{ + STDERR.reopen(STDOUT) + class C + define_method(:foo) do |&block| + block.call if block + end + result = "ng" + new.foo() {result = "ok"} + result + end +} + +assert_equal "ok", %q{ + class Bar + def bar; :ok; end + end + def foo + yield(Bar.new) if block_given? + end + foo(&:bar) +}, '[ruby-core:14279]' + +assert_normal_exit %q{ + class Controller + def respond_to(&block) + responder = Responder.new + block.call(responder) + responder.respond + end + def test_for_bug + respond_to{|format| + format.js{ + puts "in test" + render{|obj| + puts obj + } + } + } + end + def render(&block) + puts "in render" + end + end + + class Responder + def method_missing(symbol, &block) + puts "enter method_missing" + @response = Proc.new{ + puts 'in method missing' + block.call + } + puts "leave method_missing" + end + def respond + @response.call + end + end + t = Controller.new + t.test_for_bug +}, '[ruby-core:14395]' + +assert_equal 'true', %q{ + class C0 + def foo + block_given? + end + end + + class C1 < C0 + def foo + super + end + end + + C1.new.foo{} +} + +assert_equal 'true', %q{ + class C0 + def foo + block_given? + end + end + + class C1 < C0 + def foo + super() + end + end + + C1.new.foo{} +} + +assert_equal 'ok', %q{ + 1.times do + begin + raise + rescue + begin + raise + rescue + break + end + end + end + 'ok' +} diff --git a/jni/ruby/bootstraptest/test_class.rb b/jni/ruby/bootstraptest/test_class.rb new file mode 100644 index 0000000..b7fe0a1 --- /dev/null +++ b/jni/ruby/bootstraptest/test_class.rb @@ -0,0 +1,169 @@ +# class +assert_equal 'true', %q( class C; end + Object.const_defined?(:C) ) +assert_equal 'Class', %q( class C; end + C.class ) +assert_equal 'C', %q( class C; end + C.name ) +assert_equal 'C', %q( class C; end + C.new.class ) +assert_equal 'C', %q( class C; end + C.new.class.name ) +assert_equal 'Class', %q( class C; end + C.new.class.class ) +assert_equal 'true', %q( Object.__send__(:remove_const, :TrueClass) + GC.start + true.inspect) +assert_equal 'false', %q( Object.__send__(:remove_const, :FalseClass) + GC.start + false.inspect) +assert_equal 'nil', %q( Object.__send__(:remove_const, :NilClass) + GC.start + nil.inspect) + + +# inherited class +assert_equal 'true', %q( class A; end + class C < A; end + Object.const_defined?(:C) ) +assert_equal 'Class', %q( class A; end + class C < A; end + C.class ) +assert_equal 'C', %q( class A; end + class C < A; end + C.name ) +assert_equal 'C', %q( class A; end + class C < A; end + C.new.class ) +assert_equal 'C', %q( class A; end + class C < A; end + C.new.class.name ) +assert_equal 'Class', %q( class A; end + class C < A; end + C.new.class.class ) + +# module +assert_equal 'true', %q( module M; end + Object.const_defined?(:M) ) +assert_equal 'Module', %q( module M; end + M.class ) +assert_equal 'M', %q( module M; end + M.name ) +assert_equal 'C', %q( module M; end + class C; include M; end + C.new.class ) + +# nested class +assert_equal 'A::B', %q( class A; end + class A::B; end + A::B ) +assert_equal 'A::B', %q( class A; end + class A::B; end + A::B.name ) +assert_equal 'A::B', %q( class A; end + class A::B; end + A::B.new.class ) +assert_equal 'Class', %q( class A; end + class A::B; end + A::B.new.class.class ) +assert_equal 'A::B::C', %q( class A; end + class A::B; end + class A::B::C; end + A::B::C ) +assert_equal 'A::B::C', %q( class A; end + class A::B; end + class A::B::C; end + A::B::C.name ) +assert_equal 'Class', %q( class A; end + class A::B; end + class A::B::C; end + A::B::C.class ) +assert_equal 'A::B::C', %q( class A; end + class A::B; end + class A::B::C; end + A::B::C.new.class ) +assert_equal 'Class', %q( class A; end + class A::B; end + class A::B::C; end + A::B::C.new.class.class ) +assert_equal 'A::B2', %q( class A; end + class A::B; end + class A::B2 < A::B; end + A::B2 ) +assert_equal 'Class', %q( class A; end + class A::B; end + class A::B2 < A::B; end + A::B2.class ) + +# reopen +assert_equal 'true', %q( class C; end; c1 = ::C + class C; end; c2 = ::C + c1.equal?(c2) ) +assert_equal '1', %q( class C; end + class A; end + begin class C < A; end; rescue TypeError; 1 end ) +assert_equal '1', %q( class C; end + begin module C; end; rescue TypeError; 1 end ) +assert_equal '1', %q( C = 1 # [yarv-dev:782] + begin class C; end; rescue TypeError; 1 end ) +assert_equal '1', %q( C = 1 # [yarv-dev:800] + begin module C; end; rescue TypeError; 1 end ) + +# colon2, colon3 +assert_equal '1', %q( class A; end; A::C = 1; A::C ) +assert_equal '1', %q( A = 7; begin A::C = 7; rescue TypeError; 1 end ) +assert_equal '1', %q( begin 7::C = 7; rescue TypeError; 1 end ) +assert_equal 'C', %q( class A; class ::C; end end; C ) +assert_equal 'Class', %q( class A; class ::C; end end; C.class ) +assert_equal 'OK', %q( class A; ::C = "OK"; end; C ) +assert_equal 'String', %q( class A; ::C = "OK"; end; C.class ) + +# class/module dup +assert_equal 'Class', %q( class C; end; C.dup.class ) +assert_equal 'Module', %q( module M; end; M.dup.class ) + + +assert_equal "ok", %q{ + module Foo + end + + begin + def foo(&b) + Foo.module_eval &b + end + foo{ + def bar + end + } + bar() + rescue NameError + :ok + end +}, '[ruby-core:14378]' + +assert_equal '3', %q{ + $i = 0 + class C + def self.const_missing *args + $i+=1 + end + end + + 3.times{ + C::FOO + } + $i +} + +assert_match /::C\z/, %q{ + c = nil + Module.new{|m| c = class m::C; name; end} + c +}, '[ruby-dev:38456]' + +assert_normal_exit %q{ + s = Symbol.dup + class << s + end + s.allocate.to_s +}, '[ruby-core:30843]' diff --git a/jni/ruby/bootstraptest/test_eval.rb b/jni/ruby/bootstraptest/test_eval.rb new file mode 100644 index 0000000..bf74780 --- /dev/null +++ b/jni/ruby/bootstraptest/test_eval.rb @@ -0,0 +1,324 @@ +assert_equal %q{ok}, %q{ + def m + a = :ok + $b = binding + end + m + eval('a', $b) +} +assert_equal %q{[:ok, :ok2]}, %q{ + def m + a = :ok + $b = binding + end + m + eval('b = :ok2', $b) + eval('[a, b]', $b) +} +assert_equal %q{[nil, 1]}, %q{ + $ans = [] + def m + $b = binding + end + m + $ans << eval(%q{ + $ans << eval(%q{ + a + }, $b) + a = 1 + }, $b) + $ans +} +assert_equal %q{C}, %q{ + Const = :top + class C + Const = :C + def m + binding + end + end + eval('Const', C.new.m) +} +assert_equal %q{top}, %q{ + Const = :top + a = 1 + class C + Const = :C + def m + eval('Const', TOPLEVEL_BINDING) + end + end + C.new.m +} +assert_equal %q{:ok +ok}, %q{ + class C + $b = binding + end + eval %q{ + def m + :ok + end + }, $b + p C.new.m +} +assert_equal %q{ok}, %q{ + b = proc{ + a = :ok + binding + }.call + a = :ng + eval("a", b) +} +assert_equal %q{C}, %q{ + class C + def foo + binding + end + end + C.new.foo.eval("self.class.to_s") +} +assert_equal %q{1}, %q{ + eval('1') +} +assert_equal %q{1}, %q{ + eval('a=1; a') +} +assert_equal %q{1}, %q{ + a = 1 + eval('a') +} +assert_equal %q{ok}, %q{ + __send__ :eval, %{ + :ok + } +} +assert_equal %q{ok}, %q{ + 1.__send__ :instance_eval, %{ + :ok + } +} +assert_equal %q{1}, %q{ + 1.instance_eval{ + self + } +} +assert_equal %q{foo}, %q{ + 'foo'.instance_eval{ + self + } +} +assert_equal %q{1}, %q{ + class Fixnum + Const = 1 + end + 1.instance_eval %{ + Const + } +} +assert_equal %q{top}, %q{ + Const = :top + class C + Const = :C + end + C.module_eval{ + Const + } +} +assert_equal %q{C}, %q{ + Const = :top + class C + Const = :C + end + C.class_eval %{ + def m + Const + end + } + C.new.m +} +assert_equal %q{top}, %q{ + Const = :top + class C + Const = :C + end + C.class_eval{ + def m + Const + end + } + C.new.m +} +assert_equal %q{[:top, :C, :top, :C]}, %q{ + Const = :top + class C + Const = :C + end + $nest = false + $ans = [] + def m + $ans << Const + C.module_eval %{ + $ans << Const + Boo = false unless defined? Boo + unless $nest + $nest = true + m + end + } + end + m + $ans +} +assert_equal %q{[10, main]}, %q{ + $nested = false + $ans = [] + $pr = proc{ + $ans << self + unless $nested + $nested = true + $pr.call + end + } + class C + def initialize &b + 10.instance_eval(&b) + end + end + C.new(&$pr) + $ans +} + +%w[break next redo].each do |keyword| + assert_match %r"Can't escape from eval with #{keyword}\z", %{ + begin + eval "0 rescue #{keyword}" + rescue SyntaxError => e + e.message + end + }, '[ruby-dev:31372]' +end + +assert_normal_exit %q{ + STDERR.reopen(STDOUT) + class Foo + def self.add_method + class_eval("def some-bad-name; puts 'hello' unless @some_variable.some_function(''); end") + end + end + Foo.add_method +}, '[ruby-core:14556] reported by Frederick Cheung' + +assert_equal 'ok', %q{ + class Module + def my_module_eval(&block) + module_eval(&block) + end + end + class String + Integer.my_module_eval do + def hoge; end + end + end + if Integer.instance_methods(false).map{|m|m.to_sym}.include?(:hoge) && + !String.instance_methods(false).map{|m|m.to_sym}.include?(:hoge) + :ok + else + :ng + end +}, "[ruby-dev:34236]" + +assert_equal 'ok', %q{ + begin + eval("class nil::Foo; end") + :ng + rescue Exception + :ok + end +} + +assert_equal 'ok', %q{ + begin + 0.instance_eval { def m() :m end } + 1.m + :ng + rescue Exception + :ok + end +}, '[ruby-dev:34579]' + +assert_equal 'ok', %q{ + begin + 12.instance_eval { @@a } + rescue NameError + :ok + end +}, '[ruby-core:16794]' + +assert_equal 'ok', %q{ + begin + 12.instance_exec { @@a } + rescue NameError + :ok + end +}, '[ruby-core:16794]' + +assert_equal 'ok', %q{ + nil.instance_eval { + def defd_using_instance_eval() :ok end + } + nil.defd_using_instance_eval +}, '[ruby-core:28324]' + +assert_equal 'ok', %q{ + nil.instance_exec { + def defd_using_instance_exec() :ok end + } + nil.defd_using_instance_exec +}, '[ruby-core:28324]' + +assert_normal_exit %q{ + eval("", method(:proc).call {}.binding) +} + +assert_equal "", %q{ + b = binding + 10.times{ + eval('', b) + } + begin + eval('1.times{raise}', b) + rescue => e + e.message + end +}, '[ruby-dev:35392]' + +assert_equal "[:x]", %q{ + def kaboom! + yield.eval("local_variables") + end + + for x in enum_for(:kaboom!) + binding + end +}, '[ruby-core:25125]' + +assert_normal_exit %q{ + hash = {} + ("aaaa".."matz").each_with_index do |s, i| + hash[s] = i + end + begin + eval "class C; @@h = #{hash.inspect}; end" + end +}, '[ruby-core:25714]' + +assert_normal_exit %q{ + begin + eval("# encoding:utf-16le\nfoo") + rescue Exception => e + p e + RubyVM::InstructionSequence.compile("p:hello") + end +}, 'check escaping the internal value th->base_block' + diff --git a/jni/ruby/bootstraptest/test_exception.rb b/jni/ruby/bootstraptest/test_exception.rb new file mode 100644 index 0000000..35c8d25 --- /dev/null +++ b/jni/ruby/bootstraptest/test_exception.rb @@ -0,0 +1,432 @@ +assert_equal %q{2}, %q{ + begin + 1+1 + ensure + 2+2 + end +} +assert_equal %q{4}, %q{ + begin + 1+1 + begin + 2+2 + ensure + 3+3 + end + ensure + 4+4 + end +} +assert_equal %q{4}, %q{ + begin + 1+1 + begin + 2+2 + ensure + 3+3 + end + ensure + 4+4 + begin + 5+5 + ensure + 6+6 + end + end +} +assert_equal %q{NilClass}, %q{ + a = nil + 1.times{|e| + begin + rescue => err + end + a = err.class + } + a +} +assert_equal %q{RuntimeError}, %q{ + a = nil + 1.times{|e| + begin + raise + rescue => err + end + a = err.class + } + a +} +assert_equal %q{}, %q{ + $! +} +assert_equal %q{FOO}, %q{ + begin + raise "FOO" + rescue + $! + end +} +assert_equal %q{FOO}, %q{ + def m + $! + end + begin + raise "FOO" + rescue + m() + end +} +assert_equal %q{[#, #]}, %q{ + $ans = [] + def m + $! + end + begin + raise "FOO" + rescue + begin + raise "BAR" + rescue + $ans << m() + end + $ans << m() + end + $ans +} +assert_equal %q{[#, #]}, %q{ + $ans = [] + def m + $! + end + + begin + begin + raise "FOO" + ensure + $ans << m() + end + rescue + $ans << m() + end +} +assert_equal %q{[nil]}, %q{ + $ans = [] + def m + $! + end + def m2 + 1.times{ + begin + return + ensure + $ans << m + end + } + end + m2 + $ans +} +assert_equal %q{ok}, %q{ + begin + raise + rescue + :ok + end +} +assert_equal %q{ok}, %q{ + begin + raise + rescue + :ok + ensure + :ng + end +} +assert_equal %q{RuntimeError}, %q{ + begin + raise + rescue => e + e.class + end +} +assert_equal %q{ng}, %q{ + begin + raise + rescue StandardError + :ng + rescue Exception + :ok + end +} +assert_equal %q{c}, %q{ + begin + begin + raise "a" + rescue + raise "b" + ensure + raise "c" + end + rescue => e + e.message + end +} +assert_equal %q{33}, %q{ + def m a, b + a + b + end + m(1, begin + raise + rescue + 2 + end) + + m(10, begin + raise + rescue + 20 + ensure + 30 + end) +} +assert_equal %q{3}, %q{ + def m a, b + a + b + end + m(begin + raise + rescue + 1 + end, + begin + raise + rescue + 2 + end) +} +assert_equal %q{ok3}, %q{ + class E1 < Exception + end + + def m + yield + end + + begin + begin + begin + m{ + raise + } + rescue E1 + :ok2 + ensure + end + rescue + :ok3 + ensure + end + rescue E1 + :ok + ensure + end +} +assert_equal %q{7}, %q{ + $i = 0 + def m + iter{ + begin + $i += 1 + begin + $i += 2 + break + ensure + + end + ensure + $i += 4 + end + $i = 0 + } + end + + def iter + yield + end + m + $i +} +assert_equal %q{10}, %q{ + $i = 0 + def m + begin + $i += 1 + begin + $i += 2 + return + ensure + $i += 3 + end + ensure + $i += 4 + end + p :end + end + m + $i +} +assert_equal %q{1}, %q{ + begin + 1 + rescue + 2 + end +} +assert_equal %q{4}, %q{ + begin + 1 + begin + 2 + rescue + 3 + end + 4 + rescue + 5 + end +} +assert_equal %q{3}, %q{ + begin + 1 + rescue + 2 + else + 3 + end +} +assert_equal %q{2}, %q{ + begin + 1+1 + rescue + 2+2 + ensure + 3+3 + end + } +assert_equal %q{2}, %q{ + begin + 1+1 + rescue + 2+2 + ensure + 3+3 + end + } +assert_equal %q{6}, %q{ + begin + 1+1 + rescue + 2+2 + else + 3+3 + ensure + 4+4 + end + } +assert_equal %q{12}, %q{ + begin + 1+1 + begin + 2+2 + rescue + 3+3 + else + 4+4 + end + rescue + 5+5 + else + 6+6 + ensure + 7+7 + end + } +assert_equal %q{ok}, %q{ # + proc{ + begin + raise + break + rescue + :ok + end + }.call +} +assert_equal %q{}, %q{ + proc do + begin + raise StandardError + redo + rescue StandardError + end + end.call +} + +## +assert_match /undefined method `foo\'/, %q{#` + STDERR.reopen(STDOUT) + class C + def inspect + bar {} + end + + def bar + raise + ensure + end + end + C.new.foo +}, "[ruby-dev:31407]" + +assert_equal 'nil', %q{ + doit = false + exc = nil + t = Thread.new { + begin + doit = true + sleep 10 + ensure + exc = $! + end + } + Thread.pass until doit + t.kill + t.join + exc.inspect +}, '[ruby-dev:32608]' + +assert_equal 'exception class/object expected', %q{ + class ZeroDivisionError + def self.new(message) + 42 + end + end + begin + 1/0 + rescue Exception => e + e.message + end +}, '[ruby-core:24767]' + +assert_equal 'ok', %q{ + class C + def ===(o) + true + end + end + begin + begin + raise + rescue C.new + end + rescue TypeError + :ok + end +} diff --git a/jni/ruby/bootstraptest/test_finalizer.rb b/jni/ruby/bootstraptest/test_finalizer.rb new file mode 100644 index 0000000..22a16b1 --- /dev/null +++ b/jni/ruby/bootstraptest/test_finalizer.rb @@ -0,0 +1,8 @@ +assert_normal_exit %q{ +a1,a2,b1,b2=Array.new(4){""} +ObjectSpace.define_finalizer(b2,proc{}) +ObjectSpace.define_finalizer(b1,proc{b1.inspect}) + +ObjectSpace.define_finalizer(a2,proc{a1.inspect}) +ObjectSpace.define_finalizer(a1,proc{}) +}, '[ruby-dev:35778]' diff --git a/jni/ruby/bootstraptest/test_flip.rb b/jni/ruby/bootstraptest/test_flip.rb new file mode 100644 index 0000000..ff19486 --- /dev/null +++ b/jni/ruby/bootstraptest/test_flip.rb @@ -0,0 +1 @@ +assert_equal %q{E}, %q{$_ = "E"; eval("nil if true..~/^E/",nil,"-e"); $_} diff --git a/jni/ruby/bootstraptest/test_flow.rb b/jni/ruby/bootstraptest/test_flow.rb new file mode 100644 index 0000000..0390062 --- /dev/null +++ b/jni/ruby/bootstraptest/test_flow.rb @@ -0,0 +1,591 @@ +assert_equal %q{[1, 2, 4, 5, 6, 7, 8]}, %q{$a = []; begin; ; $a << 1 + [1,2].each{; $a << 2 + break; $a << 3 + }; $a << 4 + begin; $a << 5 + ensure; $a << 6 + end; $a << 7 +; $a << 8 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 5, 6, 7, 8]}, %q{$a = []; begin; ; $a << 1 + begin; $a << 2 + [1,2].each do; $a << 3 + break; $a << 4 + end; $a << 5 + ensure; $a << 6 + end; $a << 7 +; $a << 8 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{ok}, %q{ + ["a"].inject("ng"){|x,y| + break :ok + } +} +assert_equal %q{ok}, %q{ + unless ''.respond_to? :lines + class String + def lines + self + end + end + end + + ('a').lines.map{|e| + break :ok + } +} +assert_equal %q{[1, 2, 4, 5]}, %q{$a = []; begin; ; $a << 1 + ["a"].inject("ng"){|x,y|; $a << 2 + break :ok; $a << 3 + }; $a << 4 +; $a << 5 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 4, 5]}, %q{$a = []; begin; ; $a << 1 + ('a'..'b').map{|e|; $a << 2 + break :ok; $a << 3 + }; $a << 4 +; $a << 5 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 5, 7, 8]}, %q{$a = []; begin; ; $a << 1 + [1,2].each do; $a << 2 + begin; $a << 3 + break; $a << 4 + ensure; $a << 5 + end; $a << 6 + end; $a << 7 +; $a << 8 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 4, 5, 6, 9, 10]}, %q{$a = []; begin; ; $a << 1 + i=0; $a << 2 + while i<3; $a << 3 + i+=1; $a << 4 + begin; $a << 5 + ensure; $a << 6 + break; $a << 7 + end; $a << 8 + end; $a << 9 +; $a << 10 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 4, 5, 7, 10, 11]}, %q{$a = []; begin; ; $a << 1 + i=0; $a << 2 + while i<3; $a << 3 + i+=1; $a << 4 + begin; $a << 5 + raise; $a << 6 + ensure; $a << 7 + break; $a << 8 + end; $a << 9 + end; $a << 10 +; $a << 11 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 4, 5, 7, 10, 11]}, %q{$a = []; begin; ; $a << 1 + i=0; $a << 2 + while i<3; $a << 3 + i+=1; $a << 4 + begin; $a << 5 + raise; $a << 6 + rescue; $a << 7 + break; $a << 8 + end; $a << 9 + end; $a << 10 +; $a << 11 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 5, 8, 9]}, %q{$a = []; begin; ; $a << 1 + [1,2].each do; $a << 2 + begin; $a << 3 + raise StandardError; $a << 4 + ensure; $a << 5 + break; $a << 6 + end; $a << 7 + end; $a << 8 +; $a << 9 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 5, 8, 9]}, %q{$a = []; begin; ; $a << 1 + [1,2].each do; $a << 2 + begin; $a << 3 + raise StandardError; $a << 4 + rescue; $a << 5 + break; $a << 6 + end; $a << 7 + end; $a << 8 +; $a << 9 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 4, 6, 8, 10, 11]}, %q{$a = []; begin; ; $a << 1 + [1,2].each do; $a << 2 + begin; $a << 3 + begin; $a << 4 + break; $a << 5 + ensure; $a << 6 + end; $a << 7 + ensure; $a << 8 + end; $a << 9 + end; $a << 10 +; $a << 11 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 4, 5, 6, 7, 8, 10, 13, 3, 4, 5, 6, 7, 8, 10, 13, 3, 4, 5, 6, 7, 8, 10, 13, 14, 15]}, %q{$a = []; begin; ; $a << 1 + i = 0; $a << 2 + while i<3; $a << 3 + i+=1; $a << 4 + j = 0; $a << 5 + while j<3; $a << 6 + j+=1; $a << 7 + begin; $a << 8 + raise; $a << 9 + rescue; $a << 10 + break; $a << 11 + end; $a << 12 + end; $a << 13 + end; $a << 14 +; $a << 15 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 14, 6, 7, 8, 9, 11, 14, 6, 7, 8, 9, 11, 14, 15, 3, 4, 5, 6, 7, 8, 9, 11, 14, 6, 7, 8, 9, 11, 14, 6, 7, 8, 9, 11, 14, 15, 3, 4, 5, 6, 7, 8, 9, 11, 14, 6, 7, 8, 9, 11, 14, 6, 7, 8, 9, 11, 14, 15, 16, 17]}, %q{$a = []; begin; ; $a << 1 + i = 0; $a << 2 + while i<3; $a << 3 + i+=1; $a << 4 + j = 0; $a << 5 + while j<3; $a << 6 + j+=1; $a << 7 + 1.times{; $a << 8 + begin; $a << 9 + raise; $a << 10 + rescue; $a << 11 + break; $a << 12 + end; $a << 13 + }; $a << 14 + end; $a << 15 + end; $a << 16 +; $a << 17 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 4, 5, 6, 7, 8, 10, 13, 3, 4, 5, 6, 7, 8, 10, 13, 3, 4, 5, 6, 7, 8, 10, 13, 14, 15]}, %q{$a = []; begin; ; $a << 1 + i = 0; $a << 2 + while i<3; $a << 3 + i+=1; $a << 4 + j = 0; $a << 5 + while j<3; $a << 6 + j+=1; $a << 7 + begin; $a << 8 + raise; $a << 9 + ensure; $a << 10 + break; $a << 11 + end; $a << 12 + end; $a << 13 + end; $a << 14 +; $a << 15 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 14, 6, 7, 8, 9, 11, 14, 6, 7, 8, 9, 11, 14, 15, 3, 4, 5, 6, 7, 8, 9, 11, 14, 6, 7, 8, 9, 11, 14, 6, 7, 8, 9, 11, 14, 15, 3, 4, 5, 6, 7, 8, 9, 11, 14, 6, 7, 8, 9, 11, 14, 6, 7, 8, 9, 11, 14, 15, 16, 17]}, %q{$a = []; begin; ; $a << 1 + i = 0; $a << 2 + while i<3; $a << 3 + i+=1; $a << 4 + j = 0; $a << 5 + while j<3; $a << 6 + j+=1; $a << 7 + 1.times{; $a << 8 + begin; $a << 9 + raise; $a << 10 + ensure; $a << 11 + break; $a << 12 + end; $a << 13 + }; $a << 14 + end; $a << 15 + end; $a << 16 +; $a << 17 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 5, 8, 9]}, %q{$a = []; begin; ; $a << 1 + while true; $a << 2 + begin; $a << 3 + break; $a << 4 + ensure; $a << 5 + break; $a << 6 + end; $a << 7 + end; $a << 8 +; $a << 9 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 5, 99]}, %q{ +$a = []; +begin; ; $a << 1 + while true; $a << 2 + begin; $a << 3 + break; $a << 4 + ensure; $a << 5 + raise; $a << 6 + end; $a << 7 + end; $a << 8 +; $a << 9 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 4, 6, 8, 9, 10, 11]}, %q{$a = []; begin; ; $a << 1 + begin; $a << 2 + [1,2].each do; $a << 3 + begin; $a << 4 + break; $a << 5 + ensure; $a << 6 + end; $a << 7 + end; $a << 8 + ensure; $a << 9 + end; $a << 10 +; $a << 11 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 4, 99]}, %q{$a = []; begin; ; $a << 1 + begin; $a << 2 + raise StandardError; $a << 3 + ensure; $a << 4 + end; $a << 5 +; $a << 6 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 4]}, %q{$a = []; begin; ; $a << 1 + begin; $a << 2 + ensure; $a << 3 + end ; $a << 4 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 5, 99]}, %q{$a = []; begin; ; $a << 1 + [1,2].each do; $a << 2 + begin; $a << 3 + break; $a << 4 + ensure; $a << 5 + raise StandardError; $a << 6 + end; $a << 7 + end; $a << 8 +; $a << 9 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{3}, %q{ + def m a, b + a + b + end + m(1, + while true + break 2 + end + ) +} +assert_equal %q{4}, %q{ + def m a, b + a + b + end + m(1, + (i=0; while i<2 + i+=1 + class C + next 2 + end + end; 3) + ) +} +assert_equal %q{34}, %q{ + def m a, b + a+b + end + m(1, 1.times{break 3}) + + m(10, (1.times{next 3}; 20)) +} +assert_equal %q{[1, 2, 3, 6, 7]}, %q{$a = []; begin; ; $a << 1 + 3.times{; $a << 2 + class C; $a << 3 + break; $a << 4 + end; $a << 5 + }; $a << 6 +; $a << 7 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 4, 8, 9]}, %q{$a = []; begin; ; $a << 1 + 3.times{; $a << 2 + class A; $a << 3 + class B; $a << 4 + break; $a << 5 + end; $a << 6 + end; $a << 7 + }; $a << 8 +; $a << 9 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 2, 3, 2, 3, 6, 7]}, %q{$a = []; begin; ; $a << 1 + 3.times{; $a << 2 + class C; $a << 3 + next; $a << 4 + end; $a << 5 + }; $a << 6 +; $a << 7 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 4, 2, 3, 4, 2, 3, 4, 8, 9]}, %q{$a = []; begin; ; $a << 1 + 3.times{; $a << 2 + class C; $a << 3 + class D; $a << 4 + next; $a << 5 + end; $a << 6 + end; $a << 7 + }; $a << 8 +; $a << 9 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 6, 7]}, %q{$a = []; begin; ; $a << 1 + while true; $a << 2 + class C; $a << 3 + break; $a << 4 + end; $a << 5 + end; $a << 6 +; $a << 7 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 4, 8, 9]}, %q{$a = []; begin; ; $a << 1 + while true; $a << 2 + class C; $a << 3 + class D; $a << 4 + break; $a << 5 + end; $a << 6 + end; $a << 7 + end; $a << 8 +; $a << 9 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 3, 4, 5, 3, 4, 5, 3, 4, 5, 8, 9]}, %q{$a = []; begin; ; $a << 1 + i=0; $a << 2 + while i<3; $a << 3 + i+=1; $a << 4 + class C; $a << 5 + next 10; $a << 6 + end; $a << 7 + end; $a << 8 +; $a << 9 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{1}, %q{ + 1.times{ + while true + class C + begin + break + ensure + break + end + end + end + } +} +assert_equal %q{[1, 2, 3, 5, 2, 3, 5, 7, 8]}, %q{$a = []; begin; ; $a << 1 + [1,2].each do; $a << 2 + begin; $a << 3 + next; $a << 4 + ensure; $a << 5 + end; $a << 6 + end; $a << 7 +; $a << 8 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 2, 6, 3, 5, 7, 8]}, %q{$a = []; begin; ; $a << 1 + o = "test"; $a << 2 + def o.test(a); $a << 3 + return a; $a << 4 + ensure; $a << 5 + end; $a << 6 + o.test(123); $a << 7 +; $a << 8 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 4, 7, 5, 8, 9]}, %q{$a = []; begin; ; $a << 1 + def m1 *args; $a << 2 + ; $a << 3 + end; $a << 4 + def m2; $a << 5 + m1(:a, :b, (return 1; :c)); $a << 6 + end; $a << 7 + m2; $a << 8 +; $a << 9 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 8, 2, 3, 4, 5, 9, 10]}, %q{$a = []; begin; ; $a << 1 + def m(); $a << 2 + begin; $a << 3 + 2; $a << 4 + ensure; $a << 5 + return 3; $a << 6 + end; $a << 7 + end; $a << 8 + m; $a << 9 +; $a << 10 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 3, 11, 4, 5, 6, 7, 12, 13]}, %q{$a = []; begin; ; $a << 1 + def m2; $a << 2 + end; $a << 3 + def m(); $a << 4 + m2(begin; $a << 5 + 2; $a << 6 + ensure; $a << 7 + return 3; $a << 8 + end); $a << 9 + 4; $a << 10 + end; $a << 11 + m(); $a << 12 +; $a << 13 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[1, 16, 2, 3, 4, 5, 6, 7, 10, 11, 17, 18]}, %q{$a = []; begin; ; $a << 1 + def m; $a << 2 + 1; $a << 3 + 1.times{; $a << 4 + 2; $a << 5 + begin; $a << 6 + 3; $a << 7 + return; $a << 8 + 4; $a << 9 + ensure; $a << 10 + 5; $a << 11 + end; $a << 12 + 6; $a << 13 + }; $a << 14 + 7; $a << 15 + end; $a << 16 + m(); $a << 17 +; $a << 18 +; rescue Exception; $a << 99; end; $a} +assert_equal %q{[:ok, :ok2, :last]}, %q{ + a = [] + i = 0 + begin + while i < 1 + i+=1 + begin + begin + next + ensure + a << :ok + end + ensure + a << :ok2 + end + end + ensure + a << :last + end + a +} +assert_equal %q{[:ok, :ok2, :last]}, %q{ + a = [] + i = 0 + begin + while i < 1 + i+=1 + begin + begin + break + ensure + a << :ok + end + ensure + a << :ok2 + end + end + ensure + a << :last + end + a +} +assert_equal %q{[:ok, :ok2, :last]}, %q{ + a = [] + i = 0 + begin + while i < 1 + if i>0 + break + end + i+=1 + begin + begin + redo + ensure + a << :ok + end + ensure + a << :ok2 + end + end + ensure + a << :last + end + a +} +assert_equal %Q{ENSURE\n}, %q{ + def test + while true + return + end + ensure + puts("ENSURE") + end + test +}, '[ruby-dev:37967]' + +[['[ruby-core:28129]', %q{ + class Bug2728 + include Enumerable + define_method(:dynamic_method) do + "dynamically defined method" + end + def each + begin + yield :foo + ensure + dynamic_method + end + end + end + e = Bug2728.new +}], + ['[ruby-core:28132]', %q{ + class Bug2729 + include Enumerable + def each + begin + yield :foo + ensure + proc {}.call + end + end + end + e = Bug2729.new +}], + ['[ruby-core:39125]', %q{ + class Bug5234 + include Enumerable + def each + begin + yield :foo + ensure + proc + end + end + end + e = Bug5234.new +}], + ['[ruby-dev:45656]', %q{ + class Bug6460 + include Enumerable + def each + begin + yield :foo + ensure + 1.times { Proc.new } + end + end + end + e = Bug6460.new +}]].each do |bug, src| + assert_equal "foo", src + %q{e.detect {true}}, bug + assert_equal "true", src + %q{e.any? {true}}, bug + assert_equal "false", src + %q{e.all? {false}}, bug + assert_equal "true", src + %q{e.include?(:foo)}, bug +end + +assert_equal "foo", %q{ + class Bug6460 + def m1 + m2 {|e| + return e + } + end + + def m2 + begin + yield :foo + ensure + begin + begin + yield :foo + ensure + Proc.new + raise '' + end + rescue + end + end + end + end + Bug6460.new.m1 +}, '[ruby-dev:46372]' diff --git a/jni/ruby/bootstraptest/test_fork.rb b/jni/ruby/bootstraptest/test_fork.rb new file mode 100644 index 0000000..5de6ee1 --- /dev/null +++ b/jni/ruby/bootstraptest/test_fork.rb @@ -0,0 +1,75 @@ +assert_equal '0', %q{ + begin + GC.stress = true + pid = fork {} + Process.wait pid + $?.to_i + rescue NotImplementedError + 0 + end +}, '[ruby-dev:32404]' + +assert_finish 10, %q{ + begin + children = (1..10).map{ + Thread.start{fork{}}.value + } + while !children.empty? and pid = Process.wait + children.delete(pid) + end + rescue NotImplementedError + end +}, '[ruby-core:22158]' + +assert_normal_exit(<<'End', '[ruby-dev:37934]') + main = Thread.current + Thread.new { sleep 0.01 until main.stop?; Thread.kill main } + Process.setrlimit(:NPROC, 1) + fork {} +End + +assert_equal 'ok', %q{ + begin + r, w = IO.pipe + if pid1 = fork + w.close + r.read(1) + Process.kill("USR1", pid1) + _, s = Process.wait2(pid1) + s.success? ? :ok : :ng + else + r.close + if pid2 = fork + trap("USR1") { Time.now.to_s; Process.kill("USR2", pid2) } + w.close + Process.wait2(pid2) + else + w.close + sleep 0.2 + end + exit true + end + rescue NotImplementedError + :ok + end +}, '[ruby-core:28924]' + +assert_equal '[1, 2]', %q{ + a = [] + main = Thread.current + trap(:INT) { a.push(1).size == 2 and main.wakeup } + trap(:TERM) { a.push(2).size == 2 and main.wakeup } + pid = $$ + begin + pid = fork do + Process.kill(:INT, pid) + Process.kill(:TERM, pid) + end + Process.wait(pid) + 100.times {break if a.size > 1; sleep 0.001} + a.sort + rescue NotImplementedError + [1, 2] + end +}, '[ruby-dev:44005] [Ruby 1.9 - Bug #4950]' + diff --git a/jni/ruby/bootstraptest/test_gc.rb b/jni/ruby/bootstraptest/test_gc.rb new file mode 100644 index 0000000..eb68c98 --- /dev/null +++ b/jni/ruby/bootstraptest/test_gc.rb @@ -0,0 +1,34 @@ +assert_normal_exit %q{ +a = [] +ms = "a".."k" +("A".."Z").each do |mod| + mod = eval("module #{mod}; self; end") + ms.each do |meth| + iseq = RubyVM::InstructionSequence.compile("module #{mod}; def #{meth}; end; end") + GC.stress = true + iseq.eval + GC.stress = false + end + o = Object.new.extend(mod) + ms.each do |meth| + o.send(meth) + end +end +}, '[ruby-dev:39453]' + +assert_normal_exit %q{ +a = [] +ms = "a".."k" +("A".."Z").each do |mod| + mod = eval("module #{mod}; self; end") + ms.each do |meth| + GC.stress = true + mod.module_eval {define_method(meth) {}} + GC.stress = false + end + o = Object.new.extend(mod) + ms.each do |meth| + o.send(meth) + end +end +}, '[ruby-dev:39453]' diff --git a/jni/ruby/bootstraptest/test_io.rb b/jni/ruby/bootstraptest/test_io.rb new file mode 100644 index 0000000..1d2b193 --- /dev/null +++ b/jni/ruby/bootstraptest/test_io.rb @@ -0,0 +1,112 @@ +assert_finish 5, %q{ + r, w = IO.pipe + t1 = Thread.new { r.sysread(1) } + t2 = Thread.new { r.sysread(1) } + sleep 0.01 until t1.stop? and t2.stop? + w.write "a" + w.write "a" +}, '[ruby-dev:31866]' + +assert_finish 10, %q{ + begin + require "io/nonblock" + require "timeout" + timeout(3) do + r, w = IO.pipe + w.nonblock? + w.nonblock = true + w.write_nonblock("a" * 100000) + w.nonblock = false + t1 = Thread.new { w.write("b" * 4096) } + t2 = Thread.new { w.write("c" * 4096) } + sleep 0.5 + r.sysread(4096).length + sleep 0.5 + r.sysread(4096).length + t1.join + t2.join + end + rescue LoadError, Timeout::Error, NotImplementedError + end +}, '[ruby-dev:32566]' + +assert_finish 1, %q{ + r, w = IO.pipe + Thread.new { + w << "ab" + sleep 0.01 + w << "ab" + } + r.gets("abab") +} + +assert_equal 'ok', %q{ + require 'tmpdir' + begin + tmpname = "#{Dir.tmpdir}/ruby-btest-#{$$}-#{rand(0x100000000).to_s(36)}" + rw = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL) + rescue Errno::EEXIST + retry + end + save = STDIN.dup + STDIN.reopen(rw) + STDIN.reopen(save) + rw.close + File.unlink(tmpname) unless RUBY_PLATFORM['nacl'] + :ok +} + +assert_equal 'ok', %q{ + require 'tmpdir' + begin + tmpname = "#{Dir.tmpdir}/ruby-btest-#{$$}-#{rand(0x100000000).to_s(36)}" + rw = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL) + rescue Errno::EEXIST + retry + end + save = STDIN.dup + STDIN.reopen(rw) + STDIN.print "a" + STDIN.reopen(save) + rw.close + File.unlink(tmpname) unless RUBY_PLATFORM['nacl'] + :ok +} + +assert_equal 'ok', %q{ + dup = STDIN.dup + dupfd = dup.fileno + dupfd == STDIN.dup.fileno ? :ng : :ok +}, '[ruby-dev:46834]' + +assert_normal_exit %q{ + ARGF.set_encoding "foo" +} + +10.times do + assert_normal_exit %q{ + at_exit { p :foo } + + megacontent = "abc" * 12345678 + #File.open("megasrc", "w") {|f| f << megacontent } + + t0 = Thread.main + Thread.new { sleep 0.001 until t0.stop?; Process.kill(:INT, $$) } + + r1, w1 = IO.pipe + r2, w2 = IO.pipe + t1 = Thread.new { w1 << megacontent; w1.close } + t2 = Thread.new { r2.read; r2.close } + IO.copy_stream(r1, w2) rescue nil + w2.close + r1.close + t1.join + t2.join + }, 'megacontent-copy_stream', ["INT"], :timeout => 10 or break +end + +assert_normal_exit %q{ + r, w = IO.pipe + STDOUT.reopen(w) + STDOUT.reopen(__FILE__, "r") +}, '[ruby-dev:38131]' diff --git a/jni/ruby/bootstraptest/test_jump.rb b/jni/ruby/bootstraptest/test_jump.rb new file mode 100644 index 0000000..595aaa7 --- /dev/null +++ b/jni/ruby/bootstraptest/test_jump.rb @@ -0,0 +1,308 @@ +assert_equal %q{ok}, %q{ + def m + :ng1 + mm{ + yield + } + :ng2 + end + + def mm + :ng3 + yield + :ng4 + end + + m{ + break :ok + } +} +assert_equal %q{ok}, %q{ + 3.times{ + break :ok + } +} +assert_equal %q{}, %q{ + catch(:foo){ + throw :foo + } +} +assert_equal %q{false}, %q{ + catch(:foo){ + throw :foo, false + } +} +assert_equal %q{}, %q{ + catch(:foo){ + throw :foo, nil + } +} +assert_equal %q{ok}, %q{ + catch(:foo){ + throw :foo, :ok + } +} +assert_equal %q{}, %q{ + catch(:foo){ + 1.times{ + throw :foo + } + } +} +assert_equal %q{ok}, %q{ + catch(:foo){ + 1.times{ + throw :foo, :ok + } + } +} +assert_equal %q{ok}, %q{ + catch(:foo){ + catch(:bar){ + throw :foo, :ok + } + :ng + } +} +assert_equal %q{ok}, %q{ + catch(:foo){ + catch(:bar){ + 1.times{ + throw :foo, :ok + } + } + :ng + } +} +assert_equal %q{2}, %q{ + module Enumerable + def all_? + self.each{|e| + unless yield(e) + return false + end + } + true + end + end + + xxx = 0 + [1,2].each{|bi| + [3,4].each{|bj| + [true, nil, true].all_?{|be| be} + break + } + xxx += 1 + } + xxx +} +assert_equal %q{ok}, %q{ + def m + yield + end + + m{ + begin + ensure + break :ok + end + } +} +assert_equal %q{ok}, %q{ + def m + yield + :ok + end + i=0 + m{ + if i>10 + i*i + else + i+=1 + next + end + } +} +assert_equal %q{ok}, %q{ + def m + yield + end + + m{ + next :ok + } +} +assert_equal %q{131}, %q{ + def m + yield + 10 + end + i=0 + m{ + if i>10 + i*i + else + i+=1 + redo + end + } +} +assert_equal %q{ok}, %q{ +begin + eval %q{ + 1.times{ + retry + } + } +rescue SyntaxError + :ok +end +} +assert_equal %q{3}, %q{ + def m + return 3 + end + m +} +assert_equal %q{ok}, %q{ + def m + :ng1 + mm{ + return :ok + } + :ng2 + end + + def mm + :ng3 + yield + :ng4 + end + m +} +assert_equal %q{100}, %q{ + $i = 0 + def m + begin + iter{ + return + } + ensure + $i = 100 + end + end + + def iter + yield + end + m + $i +} +assert_equal %q{ok}, %q{ + def m + begin + raise + rescue + return :ok + end + :ng + end + m +} +assert_equal %q{1}, %q{ + def m + begin + raise + rescue + return 1 + end + end + + m +} +assert_equal %q{1}, %q{ + def m + begin + # + ensure + return 1 + end + end + + m +} +assert_equal 'ok', %q{ + begin + catch {|t| throw t, :ok } + rescue ArgumentError + :ng + end +}, '[ruby-dev:31609]' + +assert_equal "1", %q{ + catch do |t| + begin + throw t, 1 + 2 + ensure + 3 + end + end +}, "[ruby-dev:31698]" + +assert_normal_exit %q{ + f = 0 + 1.times do + begin + f += 1 + ensure + redo unless f > 2 + end + end +} + +assert_normal_exit %q{ + -> do + 1.times do + begin + raise + rescue + return + end + end + end.call +} + +assert_normal_exit %q{ + while true + begin + raise + next + rescue + end + break + end +}, '[ruby-core:28172]' + +assert_equal "true", %q{ + class Object + def return_eigenclass + class << self + return self + end + end + end + s = "foo" + s.return_eigenclass == class << s; self; end +}, '[ruby-core:21379]' + +assert_equal "true", %q{ + class Object + def yield_eigenclass + class << self + yield self + end + end + end + s = "foo" + s.yield_eigenclass {|c| c == class << s; self; end } +}, '[ruby-dev:40975]' diff --git a/jni/ruby/bootstraptest/test_literal.rb b/jni/ruby/bootstraptest/test_literal.rb new file mode 100644 index 0000000..aa65bdd --- /dev/null +++ b/jni/ruby/bootstraptest/test_literal.rb @@ -0,0 +1,231 @@ +# empty program +assert_equal '', '' +assert_equal '', ' ' +assert_equal '', "\n" + +# special const +assert_equal 'true', 'true' +assert_equal 'TrueClass', 'true.class' +assert_equal 'false', 'false' +assert_equal 'FalseClass', 'false.class' +assert_equal '', 'nil' +assert_equal 'nil', 'nil.inspect' +assert_equal 'NilClass', 'nil.class' +assert_equal 'sym', ':sym' +assert_equal ':sym', ':sym.inspect' +assert_equal 'Symbol', ':sym.class' +assert_equal '1234', '1234' +assert_equal 'Fixnum', '1234.class' +assert_equal '1234', '1_2_3_4' +assert_equal 'Fixnum', '1_2_3_4.class' +assert_equal '18', '0x12' +assert_equal 'Fixnum', '0x12.class' +assert_equal '15', '0o17' +assert_equal 'Fixnum', '0o17.class' +assert_equal '5', '0b101' +assert_equal 'Fixnum', '0b101.class' +assert_equal '123456789012345678901234567890', '123456789012345678901234567890' +assert_equal 'Bignum', '123456789012345678901234567890.class' +assert_equal '2.0', '2.0' +assert_equal 'Float', '1.3.class' + +# self +assert_equal 'main', 'self' +assert_equal 'Object', 'self.class' + +# string literal +assert_equal 'a', '?a' +assert_equal 'String', '?a.class' +assert_equal 'A', '?A' +assert_equal 'String', '?A.class' +assert_equal "\n", '?\n' +assert_equal 'String', '?\n.class' +assert_equal ' ', '?\ ' +assert_equal 'String', '?\ .class' +assert_equal 'string', "'string'" +assert_equal 'string', '"string"' +assert_equal 'string', '%(string)' +assert_equal 'string', '%q(string)' +assert_equal 'string', '%Q(string)' +assert_equal 'string string', '"string string"' +assert_equal ' ', '" "' +assert_equal "\0", '"\0"' +assert_equal "\1", '"\1"' +assert_equal "3", '"\x33"' +assert_equal "\n", '"\n"' + +# dynamic string literal +assert_equal '2', '"#{1 + 1}"' +assert_equal '16', '"#{2 ** 4}"' +assert_equal 'string', 's = "string"; "#{s}"' + +# dynamic symbol literal +assert_equal 'a3c', ':"a#{1+2}c"' +assert_equal ':a3c', ':"a#{1+2}c".inspect' +assert_equal 'Symbol', ':"a#{1+2}c".class' + +# xstring +unless nacl? + assert_equal "foo\n", %q(`echo foo`) + assert_equal "foo\n", %q(s = "foo"; `echo #{s}`) +end + +# regexp +assert_equal '', '//.source' +assert_equal 'Regexp', '//.class' +assert_equal '0', '// =~ "a"' +assert_equal '0', '// =~ ""' +assert_equal 'a', '/a/.source' +assert_equal 'Regexp', '/a/.class' +assert_equal '0', '/a/ =~ "a"' +assert_equal '0', '/test/ =~ "test"' +assert_equal '', '/test/ =~ "tes"' +assert_equal '0', 're = /test/; re =~ "test"' +assert_equal '0', 'str = "test"; /test/ =~ str' +assert_equal '0', 're = /test/; str = "test"; re =~ str' + +# dynamic regexp +assert_equal 'regexp', %q(/re#{'ge'}xp/.source) +assert_equal 'Regexp', %q(/re#{'ge'}xp/.class) + +# array +assert_equal 'Array', '[].class' +assert_equal '0', '[].size' +assert_equal '0', '[].length' +assert_equal '[]', '[].inspect' +assert_equal 'Array', '[0].class' +assert_equal '1', '[3].size' +assert_equal '[3]', '[3].inspect' +assert_equal '3', 'a = [3]; a[0]' +assert_equal 'Array', '[1,2].class' +assert_equal '2', '[1,2].size' +assert_equal '[1, 2]', '[1,2].inspect' +assert_equal 'Array', '[1,2,3,4,5].class' +assert_equal '5', '[1,2,3,4,5].size' +assert_equal '[1, 2, 3, 4, 5]', '[1,2,3,4,5].inspect' +assert_equal '1', 'a = [1,2]; a[0]' +assert_equal '2', 'a = [1,2]; a[1]' +assert_equal 'Array', 'a = [1 + 2, 3 + 4, 5 + 6]; a.class' +assert_equal '[3, 7, 11]', 'a = [1 + 2, 3 + 4, 5 + 6]; a.inspect' +assert_equal '7', 'a = [1 + 2, 3 + 4, 5 + 6]; a[1]' +assert_equal '1', '([0][0] += 1)' +assert_equal '1', '([2][0] -= 1)' +assert_equal 'Array', 'a = [obj = Object.new]; a.class' +assert_equal '1', 'a = [obj = Object.new]; a.size' +assert_equal 'true', 'a = [obj = Object.new]; a[0] == obj' +assert_equal '5', 'a = [1,2,3]; a[1] = 5; a[1]' +assert_equal 'bar', '[*:foo];:bar' +assert_equal '[1, 2]', 'def nil.to_a; [2]; end; [1, *nil]' +assert_equal '[1, 2]', 'def nil.to_a; [1, 2]; end; [*nil]' +assert_equal '[0, 1, {2=>3}]', '[0, *[1], 2=>3]', "[ruby-dev:31592]" + + +# hash +assert_equal 'Hash', '{}.class' +assert_equal '{}', '{}.inspect' +assert_equal 'Hash', '{1=>2}.class' +assert_equal '{1=>2}', '{1=>2}.inspect' +assert_equal '2', 'h = {1 => 2}; h[1]' +assert_equal '0', 'h = {1 => 2}; h.delete(1); h.size' +assert_equal '', 'h = {1 => 2}; h.delete(1); h[1]' +assert_equal '2', 'h = {"string" => "literal", "goto" => "hell"}; h.size' +assert_equal 'literal', 'h = {"string"=>"literal", "goto"=>"hell"}; h["string"]' +assert_equal 'hell', 'h = {"string"=>"literal", "goto"=>"hell"}; h["goto"]' + +# range +assert_equal 'Range', '(1..2).class' +assert_equal '1..2', '(1..2).inspect' +assert_equal '1', '(1..2).begin' +assert_equal '2', '(1..2).end' +assert_equal 'false', '(1..2).exclude_end?' +assert_equal 'Range', 'r = 1..2; r.class' +assert_equal '1..2', 'r = 1..2; r.inspect' +assert_equal '1', 'r = 1..2; r.begin' +assert_equal '2', 'r = 1..2; r.end' +assert_equal 'false', 'r = 1..2; r.exclude_end?' +assert_equal 'Range', '(1...3).class' +assert_equal '1...3', '(1...3).inspect' +assert_equal '1', '(1...3).begin' +assert_equal '3', '(1...3).end' +assert_equal 'true', '(1...3).exclude_end?' +assert_equal 'Range', 'r = (1...3); r.class' +assert_equal '1...3', 'r = (1...3); r.inspect' +assert_equal '1', 'r = (1...3); r.begin' +assert_equal '3', 'r = (1...3); r.end' +assert_equal 'true', 'r = (1...3); r.exclude_end?' +assert_equal 'Range', 'r = (1+2 .. 3+4); r.class' +assert_equal '3..7', 'r = (1+2 .. 3+4); r.inspect' +assert_equal '3', 'r = (1+2 .. 3+4); r.begin' +assert_equal '7', 'r = (1+2 .. 3+4); r.end' +assert_equal 'false', 'r = (1+2 .. 3+4); r.exclude_end?' +assert_equal 'Range', 'r = (1+2 ... 3+4); r.class' +assert_equal '3...7', 'r = (1+2 ... 3+4); r.inspect' +assert_equal '3', 'r = (1+2 ... 3+4); r.begin' +assert_equal '7', 'r = (1+2 ... 3+4); r.end' +assert_equal 'true', 'r = (1+2 ... 3+4); r.exclude_end?' +assert_equal 'Range', 'r = ("a".."c"); r.class' +assert_equal '"a".."c"', 'r = ("a".."c"); r.inspect' +assert_equal 'a', 'r = ("a".."c"); r.begin' +assert_equal 'c', 'r = ("a".."c"); r.end' + +assert_equal 'String', '__FILE__.class' +assert_equal 'Fixnum', '__LINE__.class' + +### + +assert_equal 'ok', %q{ + # this cause "called on terminated object". + ObjectSpace.each_object(Module) {|m| m.name.inspect } + :ok +} + +assert_normal_exit %q{ + begin + r = 0**-1 + r + r + rescue + end +}, '[ruby-dev:34524]' + +assert_normal_exit %q{ + begin + r = Marshal.load("\x04\bU:\rRational[\ai\x06i\x05") + r + r + rescue + end +}, '[ruby-dev:34536]' + +assert_equal 'ok', %q{ + "#{}""#{}ok" +}, '[ruby-dev:38968]' + +assert_equal 'ok', %q{ + "#{}o""#{}k""#{}" +}, '[ruby-core:25284]' + +assert_equal 'ok', %q{ # long array literal + x = nil + eval "a = [#{(1..10_000).map{'x'}.join(", ")}]" + :ok +} + +assert_equal 'ok', %q{ # long array literal (optimized) + eval "a = [#{(1..10_000).to_a.join(", ")}]" + :ok +} + +assert_equal 'ok', %q{ # long hash literal + x = nil + eval "a = {#{(1..10_000).map{|n| "#{n} => x"}.join(', ')}}" + :ok +} + +assert_equal 'ok', %q{ # long hash literal (optimized) + eval "a = {#{(1..10_000).map{|n| "#{n} => #{n}"}.join(', ')}}" + :ok +} + +assert_equal 'ok', %q{ + [print(:ok), exit] # void literal with side-effect + :dummy +} diff --git a/jni/ruby/bootstraptest/test_literal_suffix.rb b/jni/ruby/bootstraptest/test_literal_suffix.rb new file mode 100644 index 0000000..4316c9e --- /dev/null +++ b/jni/ruby/bootstraptest/test_literal_suffix.rb @@ -0,0 +1,54 @@ +# numbers with suffix +assert_equal '0/1', '0r' +assert_equal 'Rational', '0r.class' +assert_equal '1/1', '1r' +assert_equal 'Rational', '1r.class' +assert_equal '-1/1', '-1r' +assert_equal 'Rational', '(-1r).class' +assert_equal '1/1', '0x1r' +assert_equal 'Rational', '0x1r.class' +assert_equal '1/1', '0b1r' +assert_equal 'Rational', '0b1r.class' +assert_equal '1/1', '0d1r' +assert_equal 'Rational', '0d1r.class' +assert_equal '1/1', '0o1r' +assert_equal 'Rational', '0o1r.class' +assert_equal '1/1', '01r' +assert_equal 'Rational', '01r.class' +assert_equal '6/5', '1.2r' +assert_equal 'Rational', '1.2r.class' +assert_equal '-6/5', '-1.2r' +assert_equal 'Rational', '(-1.2r).class' +assert_equal '0+0i', '0i' +assert_equal 'Complex', '0i.class' +assert_equal '0+1i', '1i' +assert_equal 'Complex', '1i.class' +assert_equal '0+1i', '0x1i' +assert_equal 'Complex', '0x1i.class' +assert_equal '0+1i', '0b1i' +assert_equal 'Complex', '0b1i.class' +assert_equal '0+1i', '0d1i' +assert_equal 'Complex', '0d1i.class' +assert_equal '0+1i', '0o1i' +assert_equal 'Complex', '0o1i.class' +assert_equal '0+1i', '01i' +assert_equal 'Complex', '01i.class' +assert_equal '0+1.2i', '1.2i' +assert_equal 'Complex', '1.2i.class' +assert_equal '0+1/1i', '1ri' +assert_equal 'Complex', '1ri.class' +assert_equal '0+6/5i', '1.2ri' +assert_equal 'Complex', '1.2ri.class' +assert_equal '0+10.0i', '1e1i' +assert_equal 'Complex', '1e1i.class' +assert_equal '1', '1if true' +assert_equal '1', '1rescue nil' +assert_equal '10000000000000000001/10000000000000000000', + '1.0000000000000000001r' + +assert_equal 'syntax error, unexpected tIDENTIFIER, expecting end-of-input', + %q{begin eval('1ir', nil, '', 0); rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end} +assert_equal 'syntax error, unexpected tIDENTIFIER, expecting end-of-input', + %q{begin eval('1.2ir', nil, '', 0); rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end} +assert_equal 'syntax error, unexpected tIDENTIFIER, expecting end-of-input', + %q{begin eval('1e1r', nil, '', 0); rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end} diff --git a/jni/ruby/bootstraptest/test_load.rb b/jni/ruby/bootstraptest/test_load.rb new file mode 100644 index 0000000..e63c93a --- /dev/null +++ b/jni/ruby/bootstraptest/test_load.rb @@ -0,0 +1,27 @@ +assert_equal 'ok', %q{ + open("require-lock-test.rb", "w") {|f| + f.puts "sleep 0.1" + f.puts "module M" + f.puts "end" + } + $:.unshift Dir.pwd + vs = (1..2).map {|i| + Thread.start { + require "require-lock-test" + M + } + }.map {|t| t.value } + vs[0] == M && vs[1] == M ? :ok : :ng +}, '[ruby-dev:32048]' + +assert_equal 'ok', %q{ + %w[a a/foo b].each {|d| Dir.mkdir(d)} + open("b/foo", "w") {|f| f.puts "$ok = :ok"} + $:.replace(%w[a b]) + begin + load "foo" + $ok + rescue => e + e.message + end +}, '[ruby-dev:38097]' diff --git a/jni/ruby/bootstraptest/test_marshal.rb b/jni/ruby/bootstraptest/test_marshal.rb new file mode 100644 index 0000000..7e34176 --- /dev/null +++ b/jni/ruby/bootstraptest/test_marshal.rb @@ -0,0 +1,5 @@ + +assert_normal_exit %q{ + Marshal.load(Marshal.dump({"k"=>"v"}), lambda {|v| v}) +} + diff --git a/jni/ruby/bootstraptest/test_massign.rb b/jni/ruby/bootstraptest/test_massign.rb new file mode 100644 index 0000000..0f63dd4 --- /dev/null +++ b/jni/ruby/bootstraptest/test_massign.rb @@ -0,0 +1,183 @@ +assert_equal '[[1], 2, 3]', '*v1, (a, b) = [1,[2, 3]]; [v1, a, b]' +assert_equal '[[1], 2, 3]', '*v1,(*), (a, b) = [1,:x,[2, 3]]; [v1, a, b]' + +assert_equal '[]', '*a = *nil; a' +assert_equal '[nil]', '*a = nil; a' +assert_equal '2', 'a, a = 1, 2; a', "[ruby-dev:31522]" +assert_equal '[1, 2]', 'a, b = 1, 2' +assert_equal '[1, 2]', %q{ + ans = [] + trace_var(:$a){|v| ans << v} + trace_var(:$b){|v| ans << v} + $a, $b = 1, 2 + ans +} + +assert_equal 'ok', %q{ + r = :ok + :ng.tap {|(r)|} + r +}, '[ruby-dev:31507]' + +=begin +# generated by this script: + +3.times{|i| + 8.times{|e| + ary = (0...e).to_a + a,b,c,d,e,f = nil + vals = %w(a b c d e f) + vals[i] = '*' + vals[i] + program = "#{vals.join(", ")} = *ary" + eval(program) + ans = [a,b,c,d,e,f] + puts %Q{ + assert_equal "#{ans.inspect}", %q{ + ary = #{ary.inspect} + #{program}; [a, b, c, d, e, f] + }} + } +} +=end + + assert_equal "[[], nil, nil, nil, nil, nil]", %q{ + ary = [] + *a, b, c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[[], 0, nil, nil, nil, nil]", %q{ + ary = [0] + *a, b, c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[[], 0, 1, nil, nil, nil]", %q{ + ary = [0, 1] + *a, b, c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[[], 0, 1, 2, nil, nil]", %q{ + ary = [0, 1, 2] + *a, b, c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[[], 0, 1, 2, 3, nil]", %q{ + ary = [0, 1, 2, 3] + *a, b, c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[[], 0, 1, 2, 3, 4]", %q{ + ary = [0, 1, 2, 3, 4] + *a, b, c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[[0], 1, 2, 3, 4, 5]", %q{ + ary = [0, 1, 2, 3, 4, 5] + *a, b, c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[[0, 1], 2, 3, 4, 5, 6]", %q{ + ary = [0, 1, 2, 3, 4, 5, 6] + *a, b, c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[nil, [], nil, nil, nil, nil]", %q{ + ary = [] + a, *b, c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[0, [], nil, nil, nil, nil]", %q{ + ary = [0] + a, *b, c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[0, [], 1, nil, nil, nil]", %q{ + ary = [0, 1] + a, *b, c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[0, [], 1, 2, nil, nil]", %q{ + ary = [0, 1, 2] + a, *b, c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[0, [], 1, 2, 3, nil]", %q{ + ary = [0, 1, 2, 3] + a, *b, c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[0, [], 1, 2, 3, 4]", %q{ + ary = [0, 1, 2, 3, 4] + a, *b, c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[0, [1], 2, 3, 4, 5]", %q{ + ary = [0, 1, 2, 3, 4, 5] + a, *b, c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[0, [1, 2], 3, 4, 5, 6]", %q{ + ary = [0, 1, 2, 3, 4, 5, 6] + a, *b, c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[nil, nil, [], nil, nil, nil]", %q{ + ary = [] + a, b, *c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[0, nil, [], nil, nil, nil]", %q{ + ary = [0] + a, b, *c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[0, 1, [], nil, nil, nil]", %q{ + ary = [0, 1] + a, b, *c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[0, 1, [], 2, nil, nil]", %q{ + ary = [0, 1, 2] + a, b, *c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[0, 1, [], 2, 3, nil]", %q{ + ary = [0, 1, 2, 3] + a, b, *c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[0, 1, [], 2, 3, 4]", %q{ + ary = [0, 1, 2, 3, 4] + a, b, *c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[0, 1, [2], 3, 4, 5]", %q{ + ary = [0, 1, 2, 3, 4, 5] + a, b, *c, d, e, f = *ary; [a, b, c, d, e, f] + } + + assert_equal "[0, 1, [2, 3], 4, 5, 6]", %q{ + ary = [0, 1, 2, 3, 4, 5, 6] + a, b, *c, d, e, f = *ary; [a, b, c, d, e, f] + } + + +# +assert_equal 'ok', %q{ + a,s=[],"aaa" + 300.times { a< e + e.message + end +} + +assert_equal 'wrong number of arguments (0 for 1)', %q{ + def m a; end + begin + m + rescue => e + e.message + end +} + +# default argument +assert_equal '1', 'def m(x=1) x end; m()' +assert_equal '1', 'def m(x=7) x end; m(1)' +assert_equal '1', 'def m(a,x=1) x end; m(7)' +assert_equal '1', 'def m(a,x=7) x end; m(7,1)' +assert_equal '1', 'def m(a,b,x=1) x end; m(7,7)' +assert_equal '1', 'def m(a,b,x=7) x end; m(7,7,1)' +assert_equal '1', 'def m(a,x=1,y=1) x end; m(7)' +assert_equal '1', 'def m(a,x=1,y=1) y end; m(7)' +assert_equal '1', 'def m(a,x=7,y=1) x end; m(7,1)' +assert_equal '1', 'def m(a,x=7,y=1) y end; m(7,1)' +assert_equal '1', 'def m(a,x=7,y=7) x end; m(7,1,1)' +assert_equal '1', 'def m(a,x=7,y=7) y end; m(7,1,1)' + +# rest argument +assert_equal '[]', 'def m(*a) a end; m().inspect' +assert_equal '[1]', 'def m(*a) a end; m(1).inspect' +assert_equal '[1, 2]', 'def m(*a) a end; m(1,2).inspect' +assert_equal '[]', 'def m(x,*a) a end; m(7).inspect' +assert_equal '[1]', 'def m(x,*a) a end; m(7,1).inspect' +assert_equal '[1, 2]', 'def m(x,*a) a end; m(7,1,2).inspect' +assert_equal '[]', 'def m(x,y,*a) a end; m(7,7).inspect' +assert_equal '[1]', 'def m(x,y,*a) a end; m(7,7,1).inspect' +assert_equal '[1, 2]', 'def m(x,y,*a) a end; m(7,7,1,2).inspect' +assert_equal '[]', 'def m(x,y=7,*a) a end; m(7).inspect' +assert_equal '[]', 'def m(x,y,z=7,*a) a end; m(7,7).inspect' +assert_equal '[]', 'def m(x,y,z=7,*a) a end; m(7,7,7).inspect' +assert_equal '[]', 'def m(x,y,z=7,zz=7,*a) a end; m(7,7,7).inspect' +assert_equal '[]', 'def m(x,y,z=7,zz=7,*a) a end; m(7,7,7,7).inspect' +assert_equal '1', 'def m(x,y,z=7,zz=1,*a) zz end; m(7,7,7).inspect' +assert_equal '1', 'def m(x,y,z=7,zz=1,*a) zz end; m(7,7,7).inspect' +assert_equal '1', 'def m(x,y,z=7,zz=7,*a) zz end; m(7,7,7,1).inspect' + +# block argument +assert_equal 'Proc', 'def m(&block) block end; m{}.class' +assert_equal 'nil', 'def m(&block) block end; m().inspect' +assert_equal 'Proc', 'def m(a,&block) block end; m(7){}.class' +assert_equal 'nil', 'def m(a,&block) block end; m(7).inspect' +assert_equal '1', 'def m(a,&block) a end; m(1){}' +assert_equal 'Proc', 'def m(a,b=nil,&block) block end; m(7){}.class' +assert_equal 'nil', 'def m(a,b=nil,&block) block end; m(7).inspect' +assert_equal 'Proc', 'def m(a,b=nil,&block) block end; m(7,7){}.class' +assert_equal '1', 'def m(a,b=nil,&block) b end; m(7,1){}' +assert_equal 'Proc', 'def m(a,b=nil,*c,&block) block end; m(7){}.class' +assert_equal 'nil', 'def m(a,b=nil,*c,&block) block end; m(7).inspect' +assert_equal '1', 'def m(a,b=nil,*c,&block) a end; m(1).inspect' +assert_equal '1', 'def m(a,b=1,*c,&block) b end; m(7).inspect' +assert_equal '1', 'def m(a,b=7,*c,&block) b end; m(7,1).inspect' +assert_equal '[1]', 'def m(a,b=7,*c,&block) c end; m(7,7,1).inspect' + +# splat +assert_equal '1', 'def m(a) a end; m(*[1])' +assert_equal '1', 'def m(x,a) a end; m(7,*[1])' +assert_equal '1', 'def m(x,y,a) a end; m(7,7,*[1])' +assert_equal '1', 'def m(a,b) a end; m(*[1,7])' +assert_equal '1', 'def m(a,b) b end; m(*[7,1])' +assert_equal '1', 'def m(x,a,b) b end; m(7,*[7,1])' +assert_equal '1', 'def m(x,y,a,b) b end; m(7,7,*[7,1])' +assert_equal '1', 'def m(a,b,c) a end; m(*[1,7,7])' +assert_equal '1', 'def m(a,b,c) b end; m(*[7,1,7])' +assert_equal '1', 'def m(a,b,c) c end; m(*[7,7,1])' +assert_equal '1', 'def m(x,a,b,c) a end; m(7,*[1,7,7])' +assert_equal '1', 'def m(x,y,a,b,c) a end; m(7,7,*[1,7,7])' + +# hash argument +assert_equal '1', 'def m(h) h end; m(7=>1)[7]' +assert_equal '1', 'def m(h) h end; m(7=>1).size' +assert_equal '1', 'def m(h) h end; m(7=>1, 8=>7)[7]' +assert_equal '2', 'def m(h) h end; m(7=>1, 8=>7).size' +assert_equal '1', 'def m(h) h end; m(7=>1, 8=>7, 9=>7)[7]' +assert_equal '3', 'def m(h) h end; m(7=>1, 8=>7, 9=>7).size' +assert_equal '1', 'def m(x,h) h end; m(7, 7=>1)[7]' +assert_equal '1', 'def m(x,h) h end; m(7, 7=>1, 8=>7)[7]' +assert_equal '1', 'def m(x,h) h end; m(7, 7=>1, 8=>7, 9=>7)[7]' +assert_equal '1', 'def m(x,y,h) h end; m(7,7, 7=>1)[7]' +assert_equal '1', 'def m(x,y,h) h end; m(7,7, 7=>1, 8=>7)[7]' +assert_equal '1', 'def m(x,y,h) h end; m(7,7, 7=>1, 8=>7, 9=>7)[7]' + +# block argument +assert_equal '1', %q(def m(&block) mm(&block) end + def mm() yield 1 end + m {|a| a }) +assert_equal '1', %q(def m(x,&block) mm(x,&block) end + def mm(x) yield 1 end + m(7) {|a| a }) +assert_equal '1', %q(def m(x,y,&block) mm(x,y,&block) end + def mm(x,y) yield 1 end + m(7,7) {|a| a }) + +# recursive call +assert_equal '1', %q(def m(n) n == 0 ? 1 : m(n-1) end; m(5)) + +# instance method +assert_equal '1', %q(class C; def m() 1 end end; C.new.m) +assert_equal '1', %q(class C; def m(a) a end end; C.new.m(1)) +assert_equal '1', %q(class C; def m(a = 1) a end end; C.new.m) +assert_equal '[1]', %q(class C; def m(*a) a end end; C.new.m(1).inspect) +assert_equal '1', %q( class C + def m() mm() end + def mm() 1 end + end + C.new.m ) + +# singleton method (const) +assert_equal '1', %q(class C; def C.m() 1 end end; C.m) +assert_equal '1', %q(class C; def C.m(a) a end end; C.m(1)) +assert_equal '1', %q(class C; def C.m(a = 1) a end end; C.m) +assert_equal '[1]', %q(class C; def C.m(*a) a end end; C.m(1).inspect) +assert_equal '1', %q(class C; end; def C.m() 1 end; C.m) +assert_equal '1', %q(class C; end; def C.m(a) a end; C.m(1)) +assert_equal '1', %q(class C; end; def C.m(a = 1) a end; C.m) +assert_equal '[1]', %q(class C; end; def C.m(*a) a end; C.m(1).inspect) +assert_equal '1', %q(class C; def m() 7 end end; def C.m() 1 end; C.m) +assert_equal '1', %q( class C + def C.m() mm() end + def C.mm() 1 end + end + C.m ) + +# singleton method (lvar) +assert_equal '1', %q(obj = Object.new; def obj.m() 1 end; obj.m) +assert_equal '1', %q(obj = Object.new; def obj.m(a) a end; obj.m(1)) +assert_equal '1', %q(obj = Object.new; def obj.m(a=1) a end; obj.m) +assert_equal '[1]', %q(obj = Object.new; def obj.m(*a) a end; obj.m(1)) +assert_equal '1', %q(class C; def m() 7 end; end + obj = C.new + def obj.m() 1 end + obj.m) + +# inheritance +assert_equal '1', %q(class A; def m(a) a end end + class B < A; end + B.new.m(1)) +assert_equal '1', %q(class A; end + class B < A; def m(a) a end end + B.new.m(1)) +assert_equal '1', %q(class A; def m(a) a end end + class B < A; end + class C < B; end + C.new.m(1)) + +# include +assert_equal '1', %q(class A; def m(a) a end end + module M; end + class B < A; include M; end + B.new.m(1)) +assert_equal '1', %q(class A; end + module M; def m(a) a end end + class B < A; include M; end + B.new.m(1)) + +# alias +assert_equal '1', %q( def a() 1 end + alias m a + m() ) +assert_equal '1', %q( class C + def a() 1 end + alias m a + end + C.new.m ) +assert_equal '1', %q( class C + def a() 1 end + alias :m a + end + C.new.m ) +assert_equal '1', %q( class C + def a() 1 end + alias m :a + end + C.new.m ) +assert_equal '1', %q( class C + def a() 1 end + alias :m :a + end + C.new.m ) +assert_equal '1', %q( class C + def a() 1 end + alias m a + undef a + end + C.new.m ) + +# undef +assert_equal '1', %q( class C + def m() end + undef m + end + begin C.new.m; rescue NoMethodError; 1 end ) +assert_equal '1', %q( class A + def m() end + end + class C < A + def m() end + undef m + end + begin C.new.m; rescue NoMethodError; 1 end ) +assert_equal '1', %q( class A; def a() end end # [yarv-dev:999] + class B < A + def b() end + undef a, b + end + begin B.new.a; rescue NoMethodError; 1 end ) +assert_equal '1', %q( class A; def a() end end # [yarv-dev:999] + class B < A + def b() end + undef a, b + end + begin B.new.b; rescue NoMethodError; 1 end ) + +assert_equal '3', %q{ + def m1 + 1 + end + alias m2 m1 + alias :"#{'m3'}" m1 + m1 + m2 + m3 +}, '[ruby-dev:32308]' +assert_equal '1', %q{ + def foobar + end + undef :"foo#{:bar}" + 1 +}, '[ruby-dev:32308]' +assert_equal '1', %q{ + def foobar + 1 + end + alias :"bar#{:baz}" :"foo#{:bar}" + barbaz +}, '[ruby-dev:32308]' + +# private +assert_equal '1', %q( class C + def m() mm() end + def mm() 1 end + private :mm + end + C.new.m ) +assert_equal '1', %q( class C + def m() 7 end + private :m + end + begin C.m; rescue NoMethodError; 1 end ) +assert_equal '1', %q( class C + def C.m() mm() end + def C.mm() 1 end + private_class_method :mm + end + C.m ) +assert_equal '1', %q( class C + def C.m() 7 end + private_class_method :m + end + begin C.m; rescue NoMethodError; 1 end ) +assert_equal '1', %q( class C; def m() 1 end end + C.new.m # cache + class C + alias mm m; private :mm + end + C.new.m + begin C.new.mm; 7; rescue NoMethodError; 1 end ) + +# nested method +assert_equal '1', %q( class C + def m + def mm() 1 end + end + end + C.new.m + C.new.mm ) +assert_equal '1', %q( class C + def m + def mm() 1 end + end + end + instance_eval "C.new.m; C.new.mm" ) + +# method_missing +assert_equal ':m', %q( class C + def method_missing(mid, *args) mid end + end + C.new.m.inspect ) +assert_equal ':mm', %q( class C + def method_missing(mid, *args) mid end + end + C.new.mm.inspect ) +assert_equal '[1, 2]', %q( class C + def method_missing(mid, *args) args end + end + C.new.m(1,2).inspect ) +assert_equal '1', %q( class C + def method_missing(mid, *args) yield 1 end + end + C.new.m {|a| a }) +assert_equal 'nil', %q( class C + def method_missing(mid, *args, &block) block end + end + C.new.m.inspect ) + +# send +assert_equal '1', %q( class C; def m() 1 end end; + C.new.__send__(:m) ) +assert_equal '1', %q( class C; def m() 1 end end; + C.new.send(:m) ) +assert_equal '1', %q( class C; def m(a) a end end; + C.new.send(:m,1) ) +assert_equal '1', %q( class C; def m(a,b) a end end; + C.new.send(:m,1,7) ) +assert_equal '1', %q( class C; def m(x,a=1) a end end; + C.new.send(:m,7) ) +assert_equal '1', %q( class C; def m(x,a=7) a end end; + C.new.send(:m,7,1) ) +assert_equal '[1, 2]', %q( class C; def m(*a) a end end; + C.new.send(:m,1,2).inspect ) +assert_equal '1', %q( class C; def m() 7 end; private :m end + begin C.new.public_send(:m); rescue NoMethodError; 1 end ) +assert_equal '1', %q( class C; def m() 1 end; private :m end + C.new.send(:m) ) + +# with block +assert_equal '[[:ok1, :foo], [:ok2, :foo, :bar]]', +%q{ + class C + def [](a) + $ary << [yield, a] + end + def []=(a, b) + $ary << [yield, a, b] + end + end + + $ary = [] + C.new[:foo, &lambda{:ok1}] + C.new[:foo, &lambda{:ok2}] = :bar + $ary +} + +# with +assert_equal '[:ok1, [:ok2, 11]]', %q{ + class C + def [] + $ary << :ok1 + 10 + end + def []=(a) + $ary << [:ok2, a] + end + end + $ary = [] + C.new[]+=1 + $ary +} + +# splat and block arguments +assert_equal %q{[[[:x, :y, :z], NilClass], [[1, :x, :y, :z], NilClass], [[1, 2, :x, :y, :z], NilClass], [[:obj], NilClass], [[1, :obj], NilClass], [[1, 2, :obj], NilClass], [[], Proc], [[1], Proc], [[1, 2], Proc], [[], Proc], [[1], Proc], [[1, 2], Proc], [[:x, :y, :z], Proc], [[1, :x, :y, :z], Proc], [[1, 2, :x, :y, :z], Proc]]}, %q{ +def m(*args, &b) + $result << [args, b.class] +end +$result = [] +ary = [:x, :y, :z] +obj = :obj +b = Proc.new{} + +m(*ary) +m(1,*ary) +m(1,2,*ary) +m(*obj) +m(1,*obj) +m(1,2,*obj) +m(){} +m(1){} +m(1,2){} +m(&b) +m(1,&b) +m(1,2,&b) +m(*ary,&b) +m(1,*ary,&b) +m(1,2,*ary,&b) +$result +} + +# aset and splat +assert_equal '4', %q{class Foo;def []=(a,b,c,d);end;end;Foo.new[1,*a=[2,3]]=4} +assert_equal '4', %q{class Foo;def []=(a,b,c,d);end;end;def m(&blk)Foo.new[1,*a=[2,3],&blk]=4;end;m{}} + +# post test +assert_equal %q{[1, 2, :o1, :o2, [], 3, 4, NilClass, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4)} + +assert_equal %q{[1, 2, 3, :o2, [], 4, 5, NilClass, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5)} + +assert_equal %q{[1, 2, 3, 4, [], 5, 6, NilClass, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6)} + +assert_equal %q{[1, 2, 3, 4, [5], 6, 7, NilClass, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7)} + +assert_equal %q{[1, 2, 3, 4, [5, 6], 7, 8, NilClass, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7, 8)} + +assert_equal %q{[1, 2, 3, 4, [5, 6, 7], 8, 9, NilClass, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7, 8, 9)} + +assert_equal %q{[1, 2, 3, 4, [5, 6, 7, 8], 9, 10, NilClass, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)} + +assert_equal %q{[1, 2, 3, 4, [5, 6, 7, 8, 9], 10, 11, NilClass, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)} + +assert_equal %q{[1, 2, :o1, :o2, [], 3, 4, Proc, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4){}} + +assert_equal %q{[1, 2, 3, :o2, [], 4, 5, Proc, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5){}} + +assert_equal %q{[1, 2, 3, 4, [], 5, 6, Proc, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6){}} + +assert_equal %q{[1, 2, 3, 4, [5], 6, 7, Proc, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7){}} + +assert_equal %q{[1, 2, 3, 4, [5, 6], 7, 8, Proc, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7, 8){}} + +assert_equal %q{[1, 2, 3, 4, [5, 6, 7], 8, 9, Proc, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7, 8, 9){}} + +assert_equal %q{[1, 2, 3, 4, [5, 6, 7, 8], 9, 10, Proc, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7, 8, 9, 10){}} + +assert_equal %q{[1, 2, 3, 4, [5, 6, 7, 8, 9], 10, 11, Proc, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11){}} + +assert_equal %q{[1, 2, :o1, :o2, [], 3, 4, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, x, y] +end +; m(1, 2, 3, 4)} + +assert_equal %q{[1, 2, 3, :o2, [], 4, 5, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, x, y] +end +; m(1, 2, 3, 4, 5)} + +assert_equal %q{[1, 2, 3, 4, [], 5, 6, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, x, y] +end +; m(1, 2, 3, 4, 5, 6)} + + +# +# super +# +=begin +# below programs are generated by this program: + +BASE = <; super; end; end +EOS__ + +tests = { +%q{ + def m +} => %q{ + C1.new.m +}, +# +%q{ + def m a +} => %q{ + C1.new.m 1 +}, +%q{ + def m a + a = :a +} => %q{ + C1.new.m 1 +}, +# +%q{ + def m a, o=:o +} => %q{ + C1.new.m 1 + C1.new.m 1, 2 +}, +%q{ + def m a, o=:o + a = :a +} => %q{ + C1.new.m 1 + C1.new.m 1, 2 +}, +%q{ + def m a, o=:o + o = :x +} => %q{ + C1.new.m 1 + C1.new.m 1, 2 +}, +# +%q{ + def m a, *r +} => %q{ + C1.new.m 1 + C1.new.m 1, 2 + C1.new.m 1, 2, 3 +}, +%q{ + def m a, *r + r = [:x, :y] +} => %q{ + C1.new.m 1 + C1.new.m 1, 2 + C1.new.m 1, 2, 3 +}, +# +%q{ + def m a, o=:o, *r +} => %q{ + C1.new.m 1 + C1.new.m 1, 2 + C1.new.m 1, 2, 3 + C1.new.m 1, 2, 3, 4 +}, +# +%q{ + def m a, o=:o, *r, &b +} => %q{ + C1.new.m 1 + C1.new.m 1, 2 + C1.new.m 1, 2, 3 + C1.new.m 1, 2, 3, 4 + C1.new.m(1){} + C1.new.m(1, 2){} + C1.new.m(1, 2, 3){} + C1.new.m(1, 2, 3, 4){} +}, +# +"def m(m1, m2, o1=:o1, o2=:o2, p1, p2)" => +%q{ +C1.new.m(1,2,3,4) +C1.new.m(1,2,3,4,5) +C1.new.m(1,2,3,4,5,6) +}, +# +"def m(m1, m2, *r, p1, p2)" => +%q{ +C1.new.m(1,2,3,4) +C1.new.m(1,2,3,4,5) +C1.new.m(1,2,3,4,5,6) +C1.new.m(1,2,3,4,5,6,7) +C1.new.m(1,2,3,4,5,6,7,8) +}, +# +"def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2)" => +%q{ +C1.new.m(1,2,3,4) +C1.new.m(1,2,3,4,5) +C1.new.m(1,2,3,4,5,6) +C1.new.m(1,2,3,4,5,6,7) +C1.new.m(1,2,3,4,5,6,7,8) +C1.new.m(1,2,3,4,5,6,7,8,9) +}, + +### +} + + +tests.each{|setup, methods| setup = setup.dup; setup.strip! + setup = BASE.gsub(//){setup} + methods.split(/\n/).each{|m| m = m.dup; m.strip! + next if m.empty? + expr = "#{setup}; #{m}" + result = eval(expr) + puts "assert_equal %q{#{result.inspect}}, %q{\n#{expr}}" + puts + } +} + +=end + +assert_equal %q{[:C0_m, [1, 2, :o1, :o2, 3, 4]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, p1, p2); super; end; end +; C1.new.m(1,2,3,4)} + +assert_equal %q{[:C0_m, [1, 2, 3, :o2, 4, 5]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5, 6]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5,6)} + +assert_equal %q{[:C0_m, [1, :o]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [1, 2]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r; super; end; end +; C1.new.m 1, 2} + +assert_equal %q{[:C0_m, [1, 2, 3]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r; super; end; end +; C1.new.m 1, 2, 3} + +assert_equal %q{[:C0_m, [1, 2, 3, 4]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r; super; end; end +; C1.new.m 1, 2, 3, 4} + +assert_equal %q{[:C0_m, [:a]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a + a = :a; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [1, 2, 3, 4]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5, 6]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5,6)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5, 6, 7]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5,6,7)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5, 6, 7, 8]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5,6,7,8)} + +assert_equal %q{[:C0_m, [1, :o]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r, &b; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [1, 2]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r, &b; super; end; end +; C1.new.m 1, 2} + +assert_equal %q{[:C0_m, [1, 2, 3]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r, &b; super; end; end +; C1.new.m 1, 2, 3} + +assert_equal %q{[:C0_m, [1, 2, 3, 4]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r, &b; super; end; end +; C1.new.m 1, 2, 3, 4} + +assert_equal %q{[:C0_m, [1, :o]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r, &b; super; end; end +; C1.new.m(1){}} + +assert_equal %q{[:C0_m, [1, 2]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r, &b; super; end; end +; C1.new.m(1, 2){}} + +assert_equal %q{[:C0_m, [1, 2, 3]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r, &b; super; end; end +; C1.new.m(1, 2, 3){}} + +assert_equal %q{[:C0_m, [1, 2, 3, 4]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r, &b; super; end; end +; C1.new.m(1, 2, 3, 4){}} + +assert_equal %q{[:C0_m, [1, :x]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o + o = :x; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [1, :x]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o + o = :x; super; end; end +; C1.new.m 1, 2} + +assert_equal %q{[:C0_m, [:a, :o]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o + a = :a; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [:a, 2]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o + a = :a; super; end; end +; C1.new.m 1, 2} + +assert_equal %q{[:C0_m, [1]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [1, :x, :y]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, *r + r = [:x, :y]; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [1, :x, :y]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, *r + r = [:x, :y]; super; end; end +; C1.new.m 1, 2} + +assert_equal %q{[:C0_m, [1, :x, :y]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, *r + r = [:x, :y]; super; end; end +; C1.new.m 1, 2, 3} + +assert_equal %q{[:C0_m, [1, 2, :o1, :o2, 3, 4]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4)} + +assert_equal %q{[:C0_m, [1, 2, 3, :o2, 4, 5]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5, 6]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5,6)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5, 6, 7]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5,6,7)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5, 6, 7, 8]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5,6,7,8)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5, 6, 7, 8, 9]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5,6,7,8,9)} + +assert_equal %q{[:C0_m, [1]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, *r; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [1, 2]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, *r; super; end; end +; C1.new.m 1, 2} + +assert_equal %q{[:C0_m, [1, 2, 3]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, *r; super; end; end +; C1.new.m 1, 2, 3} + +assert_equal %q{[:C0_m, []]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m; super; end; end +; C1.new.m} + +assert_equal %q{[:C0_m, [1, :o]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [1, 2]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o; super; end; end +; C1.new.m 1, 2} + +assert_equal 'ok', %q{ + class C + def x=(n) + end + def m + self.x = :ok + end + end + C.new.m +} + +assert_equal 'ok', %q{ + proc{ + $SAFE = 1 + class C + def m + :ok + end + end + }.call + C.new.m +}, '[ruby-core:11998]' + +assert_equal 'ok', %q{ + proc{ + $SAFE = 2 + class C + def m + :ok + end + end + }.call + C.new.m +}, '[ruby-core:11998]' + +assert_equal 'ok', %q{ + proc{ + $SAFE = 3 + class C + def m + :ng + end + end + }.call + begin + C.new.m + rescue SecurityError + :ok + end +}, '[ruby-core:11998]' + +assert_equal 'ok', %q{ + class B + def m() :fail end + end + class C < B + undef m + begin + remove_method :m + rescue NameError + end + end + begin + C.new.m + rescue NameError + :ok + end +}, '[ruby-dev:31816], [ruby-dev:31817]' + +assert_normal_exit %q{ + begin + Process.setrlimit(Process::RLIMIT_STACK, 4_206_592) + # FreeBSD SEGVs this less than 4M + 12K bytes. + rescue Exception + exit + end + class C + attr "a" * (10*1024*1024) + end +}, '[ruby-dev:31818]' + +assert_equal 'ok', %q{ + class Module + def define_method2(name, &block) + define_method(name, &block) + end + end + class C + define_method2(:m) {|x, y| :fail } + end + begin + C.new.m([1,2]) + rescue ArgumentError + :ok + end +} + +assert_not_match /method_missing/, %q{ + STDERR.reopen(STDOUT) + variable_or_mehtod_not_exist +} + +assert_equal '[false, false, false, false, true, true]', %q{ + class C + define_method(:foo) { + block_given? + } + end + + C.new.foo {} + + class D + def foo + D.module_eval{ + define_method(:m1){ + block_given? + } + } + end + def bar + D.module_eval{ + define_method(:m2){ + block_given? + } + } + end + end + + D.new.foo + D.new.bar{} + [C.new.foo, C.new.foo{}, D.new.m1, D.new.m1{}, D.new.m2, D.new.m2{}] +}, '[ruby-core:14813]' + +assert_equal 'ok', %q{ + class Foo + define_method(:foo) do |&b| + b.call + end + end + Foo.new.foo do + break :ok + end +}, '[ruby-dev:36028]' + +assert_equal '[1, 2, [3, 4]]', %q{ + def regular(a, b, *c) + [a, b, c] + end + regular(*[], 1, *[], *[2, 3], *[], 4) +}, '[ruby-core:19413]' + +assert_equal '[1, [:foo, 3, 4, :foo]]', %q{ + def regular(a, *b) + [a, b] + end + a = b = [:foo] + regular(1, *a, *[3, 4], *b) +} + +assert_equal '["B", "A"]', %q{ + class A + def m + 'A' + end + end + + class B < A + define_method(:m) do + ['B', super()] + end + end + + class C < B + end + + C.new.m +} + +assert_equal 'ok', %q{ + module Foo + def foo + begin + super + rescue NoMethodError + :ok + end + end + module_function :foo + end + Foo.foo +}, '[ruby-dev:37587]' + +assert_equal 'Object#foo', %q{ + class Object + def self.foo + "Object.foo" + end + def foo + "Object#foo" + end + end + + module Foo + def foo + begin + super + rescue NoMethodError + :ok + end + end + module_function :foo + end + Foo.foo +}, '[ruby-dev:37587]' + +assert_normal_exit %q{ + class BasicObject + remove_method :method_missing + end + begin + "a".lalala! + rescue NoMethodError => e + e.message == "undefined method `lalala!' for \"a\":String" ? :ok : :ng + end +}, '[ruby-core:22298]' + +assert_equal 'ok', %q{ + "hello"[0] ||= "H" + "ok" +} + +assert_equal 'ok', %q{ + "hello"[0, 1] ||= "H" + "ok" +} + +assert_equal 'ok', %q{ + class C + define_method(:foo) do + C.class_eval { remove_method(:foo) } + super() + end + end + begin + C.new.foo + rescue NoMethodError + 'ok' + end +} +assert_equal 'ok', %q{ + [0][0, &proc{}] += 21 + 'ok' +}, '[ruby-core:30534]' + +# should not cache when splat +assert_equal 'ok', %q{ + class C + attr_reader :a + def initialize + @a = 1 + end + end + + def m *args + C.new.a(*args) + end + + m() + begin + m(1) + rescue ArgumentError + 'ok' + end +} + +assert_equal 'DC', %q{ + $result = [] + + class C + def foo *args + $result << 'C' + end + end + class D + def foo *args + $result << 'D' + end + end + + o1 = $o1 = C.new + o2 = $o2 = D.new + + args = Object.new + def args.to_a + test1 $o2, nil + [] + end + def test1 o, args + o.foo(*args) + end + test1 o1, args + $result.join +} + +assert_equal 'DC', %q{ + $result = [] + + class C + def foo *args + $result << 'C' + end + end + class D + def foo *args + $result << 'D' + end + end + + o1 = $o1 = C.new + o2 = $o2 = D.new + + block = Object.new + def block.to_proc + test2 $o2, %w(a, b, c), nil + Proc.new{} + end + def test2 o, args, block + o.foo(*args, &block) + end + test2 o1, [], block + $result.join +} diff --git a/jni/ruby/bootstraptest/test_objectspace.rb b/jni/ruby/bootstraptest/test_objectspace.rb new file mode 100644 index 0000000..862a94e --- /dev/null +++ b/jni/ruby/bootstraptest/test_objectspace.rb @@ -0,0 +1,46 @@ +assert_normal_exit %q{ + eval("", TOPLEVEL_BINDING) + minobj = ObjectSpace.to_enum(:each_object).min_by {|a| a.object_id } + maxobj = ObjectSpace.to_enum(:each_object).max_by {|a| a.object_id } + (((minobj.object_id-100)..(minobj.object_id+100))+ + ((maxobj.object_id-100)..(maxobj.object_id+100))).each {|id| + begin + o = ObjectSpace._id2ref(id) + rescue RangeError + next + end + o.inspect if defined?(o.inspect) + } +}, '[ruby-dev:31911]' + +assert_normal_exit %q{ + ary = (1..10).to_a + ary.permutation(2) {|x| + if x == [1,2] + ObjectSpace.each_object(String) {|s| + s.clear if !s.frozen? && (s.length == 40 || s.length == 80) + } + end + } +}, '[ruby-dev:31982]' + +assert_normal_exit %q{ + ary = (1..100).to_a + ary.permutation(2) {|x| + if x == [1,2] + ObjectSpace.each_object(Array) {|o| o.clear if o == ary && o.object_id != ary.object_id } + end + } +}, '[ruby-dev:31985]' + +assert_normal_exit %q{ + ObjectSpace.define_finalizer("") do + Mutex.new.lock + end +}, '[ruby-dev:44049]' + +assert_normal_exit %q{ + ObjectSpace.define_finalizer("") do + Thread.new {} + end +}, '[ruby-core:37858]' diff --git a/jni/ruby/bootstraptest/test_proc.rb b/jni/ruby/bootstraptest/test_proc.rb new file mode 100644 index 0000000..c23394e --- /dev/null +++ b/jni/ruby/bootstraptest/test_proc.rb @@ -0,0 +1,483 @@ +assert_equal %q{[1, 2, 3]}, %q{ + def getproc &b + b + end + + def m + yield + end + + m{ + i = 1 + m{ + j = 2 + m{ + k = 3 + getproc{ + [i, j, k] + } + } + } + }.call +} +assert_equal %q{7}, %q{ + def make_proc(&b) + b + end + + def make_closure + a = 0 + make_proc{ + a+=1 + } + end + + cl = make_closure + cl.call + cl.call * cl.call +} +assert_equal %q{ok}, %q{ + class C + def foo + :ok + end + end + + def block + C.method(:new).to_proc + end + b = block() + b.call.foo +} +assert_equal %q{[0, 1, :last, 0, 2, :last]}, %q{ + def proc &b + b + end + + pr = [] + proc{|i_b| + p3 = proc{|j_b| + pr << proc{|k_b| + [i_b, j_b, k_b] + } + } + p3.call(1) + p3.call(2) + }.call(0) + + pr[0].call(:last).concat pr[1].call(:last) +} +assert_equal %q{12}, %q{ + def iter + yield + end + + def getproc &b + b + end + + iter{ + bvar = 3 + getproc{ + bvar2 = 4 + bvar * bvar2 + } + }.call +} +assert_equal %q{200}, %q{ + def iter + yield + end + + def getproc &b + b + end + + loc1 = 0 + pr1 = iter{ + bl1 = 1 + getproc{ + loc1 += 1 + bl1 += 1 + loc1 + bl1 + } + } + + pr2 = iter{ + bl1 = 1 + getproc{ + loc1 += 1 + bl1 += 1 + loc1 + bl1 + } + } + + pr1.call; pr2.call + pr1.call; pr2.call + pr1.call; pr2.call + (pr1.call + pr2.call) * loc1 +} +assert_equal %q{[1, 2]}, %q{ + def proc(&pr) + pr + end + + def m + a = 1 + m2{ + a + } + end + + def m2 + b = 2 + proc{ + [yield, b] + } + end + + pr = m + x = ['a', 1,2,3,4,5,6,7,8,9,0, + 1,2,3,4,5,6,7,8,9,0, + 1,2,3,4,5,6,7,8,9,0, + 1,2,3,4,5,6,7,8,9,0, + 1,2,3,4,5,6,7,8,9,0,] + pr.call +} +assert_equal %q{1}, %q{ + def proc(&pr) + pr + end + + def m + a = 1 + m2{ + a + } + end + + def m2 + b = 2 + proc{ + [yield, b] + } + 100000.times{|x| + "#{x}" + } + yield + end + m +} +assert_equal %q{[:C, :C]}, %q{ + Const = :top + class C + Const = :C + $pr = proc{ + (1..2).map{ + Const + } + } + end + $pr.call +} +assert_equal %q{top}, %q{ + Const = :top + class C + Const = :C + end + pr = proc{ + Const + } + C.class_eval %q{ + pr.call + } +} +assert_equal %q{1}, %q{ + def m(&b) + b + end + + m{|e_proctest| e_proctest}.call(1) +} +assert_equal %q{12}, %q{ + def m(&b) + b + end + + m{|e_proctest1, e_proctest2| + a = e_proctest1 * e_proctest2 * 2 + a * 3 + }.call(1, 2) +} +assert_equal %q{[[], [1], [1, 2], [1, 2, 3]]}, %q{ + [ + Proc.new{|*args| args}.call(), + Proc.new{|*args| args}.call(1), + Proc.new{|*args| args}.call(1, 2), + Proc.new{|*args| args}.call(1, 2, 3), + ] +} +assert_equal %q{[[nil, []], [1, []], [1, [2]], [1, [2, 3]]]}, %q{ + [ + Proc.new{|a, *b| [a, b]}.call(), + Proc.new{|a, *b| [a, b]}.call(1), + Proc.new{|a, *b| [a, b]}.call(1, 2), + Proc.new{|a, *b| [a, b]}.call(1, 2, 3), + ] +} +assert_equal %q{0}, %q{ + pr = proc{ + $SAFE + } + $SAFE = 1 + pr.call +} +assert_equal %q{[1, 0]}, %q{ + pr = proc{ + $SAFE += 1 + } + [pr.call, $SAFE] +} +assert_equal %q{1}, %q{ + def m(&b) + b + end + m{1}.call +} +assert_equal %q{3}, %q{ + def m(&b) + b + end + + m{ + a = 1 + a + 2 + }.call +} +assert_equal %Q{ok\n}, %q{ + class A; def get_block; proc {puts "ok"} end end + block = A.new.get_block + GC.start + block.call +}, '[ruby-core:14885]' + +assert_equal 'ok', %q{ + a = lambda {|x, y, &b| b } + b = a.curry[1] + if b.call(2){} == nil + :ng + else + :ok + end +}, '[ruby-core:15551]' + +assert_equal 'ok', %q{ + lambda { + break :ok + :ng + }.call +}, '[ruby-dev:34646]' + +assert_equal %q{[:bar, :foo]}, %q{ + def foo + klass = Class.new do + define_method(:bar) do + return :bar + end + end + [klass.new.bar, :foo] + end + foo +}, "[ ruby-Bugs-19304 ]" + +assert_equal 'ok', %q{ + $x = :ok + def def7(x, y) + x[y] + $x = :ng + end + def test_def7 + def7(lambda {|x| x.call}, Proc.new {return}) + $x = :ng + end + test_def7 + $x +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + lambda { a = lambda { return }; $x = :ng; a[]; $x = :ok }.call + $x +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + lambda { a = lambda { break }; $x = :ng; a[]; $x = :ok }.call + $x +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + def def8 + $x = :ng + lambda { a = Proc.new { return }; a[]}.call + $x = :ok + end + def8 + $x +}, '[ruby-core:17164]' + + +assert_equal 'ok', %q{ + def def9 + lambda {|a| $x = :ok; a[]; $x = :ng }.call(Proc.new { return }) + $x = :ng + end + def9 + $x +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + def def10 + $x = :ng + lambda { 1.times { return } }.call + $x = :ok + end + $x = :ok + def10 + $x +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + def def11 + yield + end + begin + lambda { def11 { return } }.call + rescue LocalJumpError + :ng + else + :ok + end +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + def def12 + b = Proc.new { $x = :ng; lambda { return }.call; $x = :ok }.call + end + def12 + $x +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + def m + pr = proc{ + proc{ + return :ok + } + }.call + pr.call + :ng + end + m() +} + +assert_equal 'ok', %q{ + class Foo + def call_it + p = Proc.new + p.call + end + end + + def give_it + proc { :ok } + end + + f = Foo.new + a_proc = give_it + f.call_it(&give_it()) +}, '[ruby-core:15711]' + +assert_equal 'foo!', %q{ + class FooProc < Proc + def initialize + @foo = "foo!" + end + + def bar + @foo + end + end + + def bar + FooProc.new &lambda{ + p 1 + } + end + + fp = bar(&lambda{ + p 2 + }) + + fp.bar +}, 'Subclass of Proc' + +assert_equal 'ok', %q{ + o = Object.new + def o.write(s); end + $stderr = o + at_exit{ + print $!.message + } + raise "ok" +} + +assert_equal 'ok', %q{ + lambda do + class A + class B + proc{return :ng}.call + end + end + end.call + :ok +} + +assert_equal 'ok', %q{ + $proc = proc{return} + begin + lambda do + class A + class B + $proc.call + end + end + end.call + :ng + rescue LocalJumpError + :ok + end +} + +assert_equal 'ok', %q{ + def x + binding + end + b = x{|a| a } + b.eval('yield("ok")') +}, '[Bug #5634]' + +assert_equal 'ok', %q{ + def x + binding + end + eval("x { 'ok' }").eval "yield" +}, '[Bug #5634]' + +assert_equal 'ok', %q{ + def x + binding + end + def m + x{ 'ok' } + end + eval('yield', m) +}, '[Bug #5634]' + diff --git a/jni/ruby/bootstraptest/test_string.rb b/jni/ruby/bootstraptest/test_string.rb new file mode 100644 index 0000000..849dcd4 --- /dev/null +++ b/jni/ruby/bootstraptest/test_string.rb @@ -0,0 +1,3 @@ +assert_normal_exit %q{ + inspect.clear +}, '[ruby-core:68110]' diff --git a/jni/ruby/bootstraptest/test_struct.rb b/jni/ruby/bootstraptest/test_struct.rb new file mode 100644 index 0000000..a65964d --- /dev/null +++ b/jni/ruby/bootstraptest/test_struct.rb @@ -0,0 +1,5 @@ +assert_equal 'Struct::Foo', %q{ + Struct.instance_eval { const_set(:Foo, nil) } + Struct.new("Foo") + Struct::Foo +} diff --git a/jni/ruby/bootstraptest/test_syntax.rb b/jni/ruby/bootstraptest/test_syntax.rb new file mode 100644 index 0000000..80eaa64 --- /dev/null +++ b/jni/ruby/bootstraptest/test_syntax.rb @@ -0,0 +1,902 @@ +assert_equal %q{4}, %q{1 && 2 && 3 && 4} +assert_equal %q{}, %q{1 && nil && 3 && 4} +assert_equal %q{}, %q{1 && 2 && 3 && nil} +assert_equal %q{false}, %q{1 && 2 && 3 && false} +assert_equal %q{4}, %q{1 and 2 and 3 and 4} +assert_equal %q{}, %q{1 and nil and 3 and 4} +assert_equal %q{}, %q{1 and 2 and 3 and nil} +assert_equal %q{false}, %q{1 and 2 and 3 and false} +assert_equal %q{}, %q{nil && true} +assert_equal %q{false}, %q{false && true} +assert_equal %q{}, %q{ + case 1 + when 2 + :ng + end} +assert_equal %q{ok}, %q{ + case 1 + when 10,20,30 + :ng1 + when 1,2,3 + :ok + when 100,200,300 + :ng2 + else + :elseng + end} +assert_equal %q{elseok}, %q{ + case 123 + when 10,20,30 + :ng1 + when 1,2,3 + :ng2 + when 100,200,300 + :ng3 + else + :elseok + end +} +assert_equal %q{ok}, %q{ + case 'test' + when /testx/ + :ng1 + when /test/ + :ok + when /tetxx/ + :ng2 + else + :ng_else + end +} +assert_equal %q{ok}, %q{ + case Object.new + when Object + :ok + end +} +assert_equal %q{ok}, %q{ + case Object + when Object.new + :ng + else + :ok + end +} +assert_equal %q{ok}, %q{ + case 'test' + when 'tes' + :ng + when 'te' + :ng + else + :ok + end +} +assert_equal %q{ok}, %q{ + case 'test' + when 'tes' + :ng + when 'te' + :ng + when 'test' + :ok + end +} +assert_equal %q{ng}, %q{ + case 'test' + when 'tes' + :ng + when /te/ + :ng + else + :ok + end +} +assert_equal %q{ok}, %q{ + case 'test' + when 'tes' + :ng + when /test/ + :ok + else + :ng + end +} +assert_equal %q{100}, %q{ + def test(arg) + case 1 + when 2 + 3 + end + return arg + end + + test(100) +} +assert_equal %q{ok}, %q{ + ary = [1, 2] + case 1 + when *ary + :ok + else + :ng + end +} +assert_equal %q{ok}, %q{ + ary = [1, 2] + case 3 + when *ary + :ng + else + :ok + end +} +assert_equal %q{ok}, %q{ + ary = [1, 2] + case 1 + when :x, *ary + :ok + when :z + :ng1 + else + :ng2 + end +} +assert_equal %q{ok}, %q{ + ary = [1, 2] + case 3 + when :x, *ary + :ng1 + when :z + :ng2 + else + :ok + end +} +assert_equal %q{[:false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :then, :false, :false, :false, :then, :false, :then, :then, :then, :false, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :false, :false, :false, :false, :false, :then, :then, :then, :then, :then, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :then, :then, :then, :false, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :then, :false, :false, :false, :then, :then, :then, :then, :then, :then, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :false, :false, :false, :false, :false, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :false, :then, :then, :then, :false, :then, :false, :false, :false, :then, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :then, :then, :then, :then, :then, :false, :false, :false, :false, :false, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :false, :false, :false, :then, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :then, :false, :then, :then, :then, :false, :false, :false, :false, :false, :false, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :false, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :false, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :false, :then, :then, :then, :then, :then, :then, :then, :then, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep, :then, :sep]}, %q{ + + def make_perm ary, num + if num == 1 + ary.map{|e| [e]} + else + base = make_perm(ary, num-1) + res = [] + base.each{|b| + ary.each{|e| + res << [e] + b + } + } + res + end + end + + def each_test + conds = make_perm(['fv', 'tv'], 3) + bangs = make_perm(['', '!'], 3) + exprs = make_perm(['and', 'or'], 3) + ['if', 'unless'].each{|syn| + conds.each{|cs| + bangs.each{|bs| + exprs.each{|es| + yield(syn, cs, bs, es) + } + } + } + } + end + + fv = false + tv = true + + $ans = [] + each_test{|syn, conds, bangs, exprs| + c1, c2, c3 = conds + bang1, bang2, bang3 = bangs + e1, e2 = exprs + eval %Q{ + #{syn} #{bang1}#{c1} #{e1} #{bang2}#{c2} #{e2} #{bang3}#{c3} + $ans << :then + else + $ans << :false + end + } + } + + each_test{|syn, conds, bangs, exprs| + c1, c2, c3 = conds + bang1, bang2, bang3 = bangs + e1, e2 = exprs + eval %Q{ + #{syn} #{bang1}#{c1} #{e1} #{bang2}#{c2} #{e2} #{bang3}#{c3} + $ans << :then + end + $ans << :sep + } + } + $ans +} +assert_equal %q{}, %q{ + defined?(m) +} +assert_equal %q{method}, %q{ + def m + end + defined?(m) +} +assert_equal %q{}, %q{ + defined?(a.class) +} +assert_equal %q{method}, %q{ + a = 1 + defined?(a.class) +} +assert_equal %q{["method", "method", "method", "method", nil, nil, "method", "method", "method", nil]}, %q{ + class C + def test + [defined?(m1()), defined?(self.m1), defined?(C.new.m1), + defined?(m2()), defined?(self.m2), defined?(C.new.m2), + defined?(m3()), defined?(self.m3), defined?(C.new.m3)] + end + def m1 + end + private + def m2 + end + protected + def m3 + end + end + C.new.test + [defined?(C.new.m3)] +} +assert_equal %q{[nil, nil, nil, nil, "global-variable", "global-variable", nil, nil]}, %q{ + $ans = [defined?($1), defined?($2), defined?($3), defined?($4)] + /(a)(b)/ =~ 'ab' + $ans + [defined?($1), defined?($2), defined?($3), defined?($4)] +} +assert_equal %q{nilselftruefalse}, %q{ + defined?(nil) + defined?(self) + + defined?(true) + defined?(false) +} +assert_equal %q{}, %q{ + defined?(@a) +} +assert_equal %q{instance-variable}, %q{ + @a = 1 + defined?(@a) +} +assert_equal %q{}, %q{ + defined?(@@a) +} +assert_equal %q{class variable}, %q{ + @@a = 1 + defined?(@@a) +} +assert_equal %q{}, %q{ + defined?($a) +} +assert_equal %q{global-variable}, %q{ + $a = 1 + defined?($a) +} +assert_equal %q{}, %q{ + defined?(C_definedtest) +} +assert_equal %q{constant}, %q{ + C_definedtest = 1 + defined?(C_definedtest) +} +assert_equal %q{}, %q{ + defined?(::C_definedtest) +} +assert_equal %q{constant}, %q{ + C_definedtest = 1 + defined?(::C_definedtest) +} +assert_equal %q{}, %q{ + defined?(C_definedtestA::C_definedtestB::C_definedtestC) +} +assert_equal %q{constant}, %q{ + class C_definedtestA + class C_definedtestB + C_definedtestC = 1 + end + end + defined?(C_definedtestA::C_definedtestB::C_definedtestC) +} +assert_equal %q{30}, %q{ + sum = 0 + 30.times{|ib| + if ib % 10 == 0 .. true + sum += ib + end + } + sum +} +assert_equal %q{63}, %q{ + sum = 0 + 30.times{|ib| + if ib % 10 == 0 ... true + sum += ib + end + } + sum +} +assert_equal %q{[["NUM", "Type: NUM\n"], ["NUM", "123\n"], ["NUM", "456\n"], ["NUM", "Type: ARP\n"], ["NUM", "aaa\n"], ["NUM", "bbb\n"], ["NUM", "\f\n"], ["ARP", "Type: ARP\n"], ["ARP", "aaa\n"], ["ARP", "bbb\n"]]}, %q{ + t = nil + unless ''.respond_to? :lines + class String + def lines + self + end + end + end + ary = [] +"this must not print +Type: NUM +123 +456 +Type: ARP +aaa +bbb +\f +this must not print +hoge +Type: ARP +aaa +bbb +".lines.each{|l| + if (t = l[/^Type: (.*)/, 1])..(/^\f/ =~ l) + ary << [t, l] + end + } + ary +} +assert_equal %q{1}, %q{if true then 1 ; end} +assert_equal %q{}, %q{if false then 1 ; end} +assert_equal %q{1}, %q{if true then 1 ; else; 2; end} +assert_equal %q{2}, %q{if false then 1 ; else; 2; end} +assert_equal %q{}, %q{if true then ; elsif true then ; 1 ; end} +assert_equal %q{1}, %q{if false then ; elsif true then ; 1 ; end} +assert_equal %q{}, %q{unless true then 1 ; end} +assert_equal %q{1}, %q{unless false then 1 ; end} +assert_equal %q{2}, %q{unless true then 1 ; else; 2; end} +assert_equal %q{1}, %q{unless false then 1 ; else; 2; end} +assert_equal %q{1}, %q{1 if true} +assert_equal %q{}, %q{1 if false} +assert_equal %q{}, %q{1 if nil} +assert_equal %q{}, %q{1 unless true} +assert_equal %q{1}, %q{1 unless false} +assert_equal %q{1}, %q{1 unless nil} +assert_equal %q{1}, %q{1 || 2 || 3 || 4} +assert_equal %q{1}, %q{1 || false || 3 || 4} +assert_equal %q{2}, %q{nil || 2 || 3 || 4} +assert_equal %q{2}, %q{false || 2 || 3 || 4} +assert_equal %q{false}, %q{nil || false || nil || false} +assert_equal %q{1}, %q{1 or 2 or 3 or 4} +assert_equal %q{1}, %q{1 or false or 3 or 4} +assert_equal %q{2}, %q{nil or 2 or 3 or 4} +assert_equal %q{2}, %q{false or 2 or 3 or 4} +assert_equal %q{false}, %q{nil or false or nil or false} +assert_equal %q{elseng}, %q{ + case + when 1==2, 2==3 + :ng1 + when false, 4==5 + :ok + when false + :ng2 + else + :elseng + end +} +assert_equal %q{ok}, %q{ + case + when nil, nil + :ng1 + when 1,2,3 + :ok + when false, false + :ng2 + else + :elseng + end +} +assert_equal %q{elseok}, %q{ + case + when nil + :ng1 + when false + :ng2 + else + :elseok + end} +assert_equal %q{}, %q{ + case + when 1 + end +} +assert_equal %q{ok}, %q{ + r = nil + ary = [] + case + when false + r = :ng1 + when false, false + r = :ng2 + when *ary + r = :ng3 + when false, *ary + r = :ng4 + when true, *ary + r = :ok + end + r +} +assert_equal %q{ok}, %q{ + ary = [] + case + when false, *ary + :ng + else + :ok + end +} +assert_equal %q{ok}, %q{ + ary = [false, nil] + case + when *ary + :ng + else + :ok + end +} +assert_equal %q{ok}, %q{ + ary = [false, nil] + case + when *ary + :ng + when true + :ok + else + :ng2 + end +} +assert_equal %q{ng}, %q{ + ary = [false, nil] + case + when *ary + :ok + else + :ng + end +} +assert_equal %q{ok}, %q{ + ary = [false, true] + case + when *ary + :ok + else + :ng + end +} +assert_equal %q{ok}, %q{ + ary = [false, true] + case + when false, false + when false, *ary + :ok + else + :ng + end +} +assert_equal %q{}, %q{ + i = 0 + while i < 10 + i+=1 + end} +assert_equal %q{10}, %q{ + i = 0 + while i < 10 + i+=1 + end; i} +assert_equal %q{}, %q{ + i = 0 + until i > 10 + i+=1 + end} +assert_equal %q{11}, %q{ + i = 0 + until i > 10 + i+=1 + end; i} +assert_equal %q{1}, %q{ + i = 0 + begin + i+=1 + end while false + i +} +assert_equal %q{1}, %q{ + i = 0 + begin + i+=1 + end until true + i +} +def assert_syntax_error expected, code, message = '' + assert_equal "#{expected}", + "begin eval(%q{#{code}}, nil, '', 0)"'; rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end', message +end +assert_syntax_error "unterminated string meets end of file", '().."', '[ruby-dev:29732]' +assert_equal %q{[]}, %q{$&;[]}, '[ruby-dev:31068]' +assert_syntax_error "syntax error, unexpected *, expecting '}'", %q{{*0}}, '[ruby-dev:31072]' +assert_syntax_error "`@0' is not allowed as an instance variable name", %q{@0..0}, '[ruby-dev:31095]' +assert_syntax_error "identifier $00 is not valid to get", %q{$00..0}, '[ruby-dev:31100]' +assert_syntax_error "identifier $00 is not valid to set", %q{0..$00=1} +assert_equal %q{0}, %q{[*0];0}, '[ruby-dev:31102]' +assert_syntax_error "syntax error, unexpected ')'", %q{v0,(*,v1,) = 0}, '[ruby-dev:31104]' +assert_equal %q{1}, %q{ + class << (ary=[]); def []; 0; end; def []=(x); super(0,x);end;end; ary[]+=1 +}, '[ruby-dev:31110]' +assert_syntax_error "Can't set variable $1", %q{0..$1=1}, '[ruby-dev:31118]' +assert_valid_syntax %q{1.times{1+(1&&next)}}, '[ruby-dev:31119]' +assert_valid_syntax %q{x=-1;loop{x+=1&&redo if (x+=1).zero?}}, '[ruby-dev:31119]' +assert_syntax_error %q{syntax error, unexpected end-of-input}, %q{!}, '[ruby-dev:31243]' +assert_equal %q{[nil]}, %q{[()]}, '[ruby-dev:31252]' +assert_equal %q{true}, %q{!_=()}, '[ruby-dev:31263]' +assert_equal 'ok', %q{while true; redo; end if 1 == 2; :ok}, '[ruby-dev:31360]' +assert_equal 'ok', %q{ + 1.times { + begin + ensure + next + end + }; :ok +}, '[ruby-dev:31373]' +assert_equal 'ok', %q{ + flag = false + 1.times { + next if flag + flag = true + begin + ensure + redo + end + }; :ok +}, '[ruby-dev:31373]' + +assert_equal 'ok', %q{ + 1.times{ + p(1, (next; 2)) + }; :ok +} +assert_equal '3', %q{ + i = 0 + 1 + (while true + break 2 if (i+=1) > 1 + next + end) +} +assert_equal '3', %q{ + i = 0 + 1 + (while true + break 2 if (i+=1) > 1 + p(1, (next; 2)) + end) +} +# redo +assert_equal 'ok', %q{ + i = 0 + 1.times{ + break if i>1 + i+=1 + p(1, (redo; 2)) + }; :ok +} +assert_equal '3', %q{ + i = 0 + 1 + (while true + break 2 if (i+=1) > 1 + redo + end) +} +assert_equal '3', %q{ + i = 0 + 1 + (while true + break 2 if (i+=1) > 1 + p(1, (redo; 2)) + end) +} +assert_equal '1', %q{ + a = [0] + a[*a]+=1 +} +assert_equal '2', %q{ + ary = [0] + case 1 + when *ary, 1 + 1 + end + + case + when *ary + 1 + end +} + +assert_match /invalid multibyte char/, %q{ + STDERR.reopen(STDOUT) + eval("\"\xf0".force_encoding("utf-8")) +}, '[ruby-dev:32429]' + +# method ! and != +assert_equal 'true', %q{!false} +assert_equal 'true', %q{1 == 1} +assert_equal 'true', %q{1 != 2} +assert_equal 'true', %q{ + class C; def !=(obj); true; end; end + C.new != 1 +} +assert_equal 'true', %q{ + class C; def !@; true; end; end + !C.new +} +assert_normal_exit %q{ + eval "while true; return; end rescue p $!" +}, '[ruby-dev:31663]' +assert_equal '1', %q{ + def bar + raise + end + + def foo + 1.times{ + begin + return bar + rescue + :ok + end + } + end + + foo +} + +assert_equal 'ok', %q{ + counter = 2 + while true + counter -= 1 + next if counter != 0 + break + end + :ok +}, '[ruby-core:14385]' + +assert_equal 'ok', %q{ + counter = 2 + while true + counter -= 1 + next if counter != 0 + break :ok + end # direct +}, '[ruby-core:14385]' + +assert_equal 'ok', %q{ + counter = 2 + while true + counter -= 1 + break if counter == 0 + "#{next}" + end + :ok +}, 'reported by Yusuke ENDOH' + +assert_equal 'ok', %q{ + counter = 2 + while true + counter -= 1 + break if counter == 0 + next + redo + end + :ok +}, 'reported by Yusuke ENDOH' + +assert_equal 'ok', %q{ + counter = 2 + while true + counter -= 1 + break if counter == 0 + next + "#{ redo }" + end + :ok +}, 'reported by Yusuke ENDOH' + +assert_normal_exit %q{ + begin + raise + rescue + counter = 2 + while true + counter -= 1 + break if counter == 0 + next + retry + end + end +}, 'reported by Yusuke ENDOH' + +assert_normal_exit %q{ + counter = 2 + while true + counter -= 1 + break if counter == 0 + next + "#{ break }" + end +}, 'reported by Yusuke ENDOH' + +assert_normal_exit %q{ + counter = 2 + while true + counter -= 1 + next if counter != 0 + "#{ break }" + end +}, 'reported by Yusuke ENDOH' + +assert_equal 'ok', %q{ + 1.times do + [ + 1, 2, 3, 4, 5, 6, 7, 8, + begin + false ? next : p + break while true + end + ] + end + :ok +}, '[ruby-dev:32882]' + +assert_equal "1\n2\n", %q{ + i = 0 + while i<2 + i += 1 + next p(i) + end +} + +assert_valid_syntax('1.times {|i|print (42),1;}', '[ruby-list:44479]') + +assert_equal 'ok', %q{ + def a() end + begin + if defined?(a(1).a) + :ng + else + :ok + end + rescue + :ng + end +}, '[ruby-core:16010]' + +assert_equal 'ok', %q{ + def a() end + begin + if defined?(a::B) + :ng + else + :ok + end + rescue + :ng + end +}, '[ruby-core:16010]' + +assert_normal_exit %q{ + defined? C && 0 +} + +assert_normal_exit %q{ + class C + def m + defined?(super()) + end + end + C.new.m +} + +assert_equal 'ok', %q{ + class X < RuntimeError;end + x = [X] + begin + raise X + rescue *x + :ok + end +}, '[ruby-core:14537]' + +assert_equal 'ok', %q{ + a = [false] + (a[0] &&= true) == false ? :ok : :ng +}, '[ruby-dev:34679]' + +assert_normal_exit %q{ + a = [] + 100.times {|i| a << i << nil << nil } + p a.compact! +} + +assert_equal 'ok', %q{ + "#{}""#{}ok" +}, '[ruby-dev:38968]' + + +assert_equal 'ok', %q{ + "o" "#{}k" +}, '[ruby-dev:38980]' + +bug2415 = '[ruby-core:26961]' +assert_normal_exit %q{ + 0.times do + 0.times do + def x(a=1, b, *rest); nil end + end + end +}, bug2415 + +assert_normal_exit %q{ + 0.times do + 0.times do + def x@; nil end + end + end +}, bug2415 + +assert_normal_exit %q{ + 0.times do + 0.times do + def x(a = 0.times do + def y(a=1, b, *rest); nil; end + end) + nil + end + end + end +}, bug2415 + +assert_normal_exit %q{ + 0.times do + 0.times do + def x(a = 0.times do + def x@; nil; end + end) + nil + end + end + end +}, bug2415 + +assert_normal_exit %q{ + a { + b {|c.d| } + e + } +}, '[ruby-dev:39861]' + +bug1240 = '[ruby-core:22637]' +assert_valid_syntax('x y { "#{}".z { } }', bug1240) +assert_valid_syntax('x y { "#{}".z do end }', bug1240) + +assert_valid_syntax('y "#{a 1}" do end', '[ruby-core:29579]') +assert_normal_exit %q{ + def foo(&block) + yield + end + + foo do + s = defined?(raise + 1) + Class + end +}, '[ruby-core:30293]' diff --git a/jni/ruby/bootstraptest/test_thread.rb b/jni/ruby/bootstraptest/test_thread.rb new file mode 100644 index 0000000..d64f44b --- /dev/null +++ b/jni/ruby/bootstraptest/test_thread.rb @@ -0,0 +1,476 @@ +# Thread and Fiber + +assert_equal %q{ok}, %q{ + Thread.new{ + }.join + :ok +} +assert_equal %q{ok}, %q{ + Thread.new{ + :ok + }.value +} +assert_equal %q{ok}, %q{ +begin + v = 0 + (1..200).map{|i| + Thread.new{ + i + } + }.each{|t| + v += t.value + } + v == 20100 ? :ok : v +rescue ThreadError => e + :ok if /can't create Thread/ =~ e.message +end +} +assert_equal %q{5000}, %q{ + 5000.times{|e| + (1..2).map{ + Thread.new{ + } + }.each{|e| + e.join() + } + } +} +assert_equal %q{5000}, %q{ + 5000.times{|e| + (1..2).map{ + Thread.new{ + } + }.each{|e| + e.join(1000000000) + } + } +} +assert_equal %q{ok}, %q{ +begin + :ok if 5000 == 5000.times{ + t = Thread.new{} + while t.alive? + Thread.pass + end + } +rescue NoMemoryError + :ok +end +} +assert_equal %q{100}, %q{ + 100.times{ + Thread.new{loop{Thread.pass}} + } +} +assert_equal %q{ok}, %q{ + Thread.new{ + :ok + }.join.value +} +assert_equal %q{ok}, %q{ + begin + Thread.new{ + raise "ok" + }.join + rescue => e + e + end +} +assert_equal %q{ok}, %q{ + ans = nil + t = Thread.new{ + begin + sleep 0.5 + ensure + ans = :ok + end + } + Thread.pass until t.stop? + t.kill + t.join + ans +} +assert_equal %q{ok}, %q{ + t = Thread.new{ + sleep + } + sleep 0.1 + t.raise + begin + t.join + :ng + rescue + :ok + end +} +assert_equal %q{ok}, %q{ + t = Thread.new{ + loop{} + } + Thread.pass + t.raise + begin + t.join + :ng + rescue + :ok + end +} +assert_equal %q{ok}, %q{ + t = Thread.new{ + } + Thread.pass + t.join + t.raise # raise to exited thread + begin + t.join + :ok + rescue + :ng + end +} +assert_equal %q{run}, %q{ + t = Thread.new{ + loop{} + } + st = t.status + t.kill + st +} +assert_equal %q{sleep}, %q{ + t = Thread.new{ + sleep + } + sleep 0.1 + st = t.status + t.kill + st +} +assert_equal %q{false}, %q{ + t = Thread.new{ + } + t.kill + sleep 0.1 + t.status +} +assert_equal %q{[ThreadGroup, true]}, %q{ + ptg = Thread.current.group + Thread.new{ + ctg = Thread.current.group + [ctg.class, ctg == ptg] + }.value +} +assert_equal %q{[1, 1]}, %q{ + thg = ThreadGroup.new + + t = Thread.new{ + thg.add Thread.current + sleep + } + sleep 0.1 + [thg.list.size, ThreadGroup::Default.list.size] +} +assert_equal %q{true}, %q{ + thg = ThreadGroup.new + + t = Thread.new{sleep 5} + thg.add t + thg.list.include?(t) +} +assert_equal %q{[true, nil, true]}, %q{ + /a/ =~ 'a' + $a = $~ + Thread.new{ + $b = $~ + /b/ =~ 'b' + $c = $~ + }.join + $d = $~ + [$a == $d, $b, $c != $d] +} +assert_equal %q{11}, %q{ + Thread.current[:a] = 1 + Thread.new{ + Thread.current[:a] = 10 + Thread.pass + Thread.current[:a] + }.value + Thread.current[:a] +} +assert_normal_exit %q{ + begin + 100.times do |i| + begin + th = Thread.start(Thread.current) {|u| u.raise } + raise + rescue + ensure + th.join + end + end + rescue + end +}, '[ruby-dev:31371]' + +assert_equal 'true', %{ + t = Thread.new { loop {} } + begin + pid = fork { + exit t.status != "run" + } + Process.wait pid + $?.success? + rescue NotImplementedError + true + end +} + +assert_equal 'ok', %{ + open("zzz.rb", "w") do |f| + f.puts <<-END + begin + Thread.new { fork { GC.start } }.join + pid, status = Process.wait2 + $result = status.success? ? :ok : :ng + rescue NotImplementedError + $result = :ok + end + END + end + require "./zzz.rb" + $result +} + +assert_finish 3, %{ + th = Thread.new {sleep 0.2} + th.join(0.1) + th.join +} + +assert_finish 3, %{ + require 'timeout' + th = Thread.new {sleep 0.2} + begin + Timeout.timeout(0.1) {th.join} + rescue Timeout::Error + end + th.join +} + +assert_normal_exit %q{ + STDERR.reopen(STDOUT) + exec "/" +} + +assert_normal_exit %q{ + (0..10).map { + Thread.new { + 10000.times { + Object.new.to_s + } + } + }.each {|t| + t.join + } +} + +assert_equal 'ok', %q{ + def m + t = Thread.new { while true; // =~ "" end } + sleep 0.01 + 10.times { + if /((ab)*(ab)*)*(b)/ =~ "ab"*7 + return :ng if !$4 + return :ng if $~.size != 5 + end + } + :ok + ensure + Thread.kill t + end + m +}, '[ruby-dev:34492]' + +assert_normal_exit %q{ + at_exit { Fiber.new{}.resume } +} + +assert_normal_exit %q{ + g = enum_for(:local_variables) + loop { g.next } +}, '[ruby-dev:34128]' + +assert_normal_exit %q{ + g = enum_for(:block_given?) + loop { g.next } +}, '[ruby-dev:34128]' + +assert_normal_exit %q{ + g = enum_for(:binding) + loop { g.next } +}, '[ruby-dev:34128]' + +assert_normal_exit %q{ + g = "abc".enum_for(:scan, /./) + loop { g.next } +}, '[ruby-dev:34128]' + +assert_normal_exit %q{ + g = Module.enum_for(:new) + loop { g.next } +}, '[ruby-dev:34128]' + +assert_normal_exit %q{ + Fiber.new(&Object.method(:class_eval)).resume("foo") +}, '[ruby-dev:34128]' + +assert_normal_exit %q{ + Thread.new("foo", &Object.method(:class_eval)).join +}, '[ruby-dev:34128]' + +assert_equal 'ok', %q{ + begin + Thread.new { Thread.stop } + Thread.stop + :ng + rescue Exception + :ok + end +} + +assert_equal 'ok', %q{ + begin + m1, m2 = Mutex.new, Mutex.new + f1 = f2 = false + Thread.new { m1.lock; f2 = true; sleep 0.001 until f1; m2.lock } + m2.lock; f1 = true; sleep 0.001 until f2; m1.lock + :ng + rescue Exception + :ok + end +} + +assert_equal 'ok', %q{ + m = Mutex.new + Thread.new { m.lock }; sleep 0.1; m.lock + :ok +} + +assert_equal 'ok', %q{ + m = Mutex.new + Thread.new { m.lock }; m.lock + :ok +} + +assert_equal 'ok', %q{ + m = Mutex.new + Thread.new { m.lock }.join; m.lock + :ok +} + +assert_equal 'ok', %q{ + m = Mutex.new + Thread.new { m.lock; sleep 0.2 } + sleep 0.1; m.lock + :ok +} + +assert_equal 'ok', %q{ + m = Mutex.new + Thread.new { m.lock; sleep 0.2; m.unlock } + sleep 0.1; m.lock + :ok +} + +assert_equal 'ok', %q{ + t = Thread.new {`echo`} + t.join + $? ? :ng : :ok +}, '[ruby-dev:35414]' + +assert_equal 'ok', %q{ + begin + 100.times{ + (1..100).map{ Thread.new(true) {|x| x == false } }.each{|th| th.join} + } + rescue NoMemoryError, StandardError + end + :ok +} + +assert_equal 'ok', %{ + open("zzz.rb", "w") do |f| + f.puts <<-'end;' # do + begin + m = Mutex.new + parent = Thread.current + th1 = Thread.new { m.lock; sleep } + sleep 0.01 until th1.stop? + Thread.new do + sleep 0.01 until parent.stop? + begin + fork { GC.start } + rescue Exception + parent.raise $! + end + th1.run + end + m.lock + pid, status = Process.wait2 + $result = status.success? ? :ok : :ng + rescue NotImplementedError + $result = :ok + end + end; + end + require "./zzz.rb" + $result +} + +assert_finish 3, %q{ + require 'thread' + + lock = Mutex.new + cond = ConditionVariable.new + t = Thread.new do + lock.synchronize do + cond.wait(lock) + end + end + + begin + pid = fork do + # Child + STDOUT.write "This is the child process.\n" + STDOUT.write "Child process exiting.\n" + end + Process.waitpid(pid) + rescue NotImplementedError + end +}, '[ruby-core:23572]' + +assert_equal 'ok', %q{ + begin + Process.waitpid2(fork {})[1].success? ? 'ok' : 'ng' + rescue NotImplementedError + 'ok' + end +} + +assert_equal 'foo', %q{ + i = 0 + Thread.start {sleep 1; exit!} + f = proc {|s, c| /#{c.call; s}/o } + th2 = Thread.new { + sleep 0.01 until i == 1 + i = 2 + f.call("bar", proc {sleep 2}); + nil + } + th1 = Thread.new { + f.call("foo", proc {i = 1; sleep 0.01 until i == 2; sleep 0.01}) + nil + } + [th1, th2].each {|t| t.join } + GC.start + f.call.source +} -- cgit v1.2.3