mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* test/ruby/test_settracefunc.rb: add a test for set_trace_func.
* test/ruby/envutil.rb: move "rubyexec" method from test_rubyoptions.rb. * test/ruby/test_rubyoptions.rb: use rubyexec in envutil.rb. * test/ruby/test_thread.rb: add tests to achieve over 90% test coverage of thread.c. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16175 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
c0d8e6cbf9
commit
f7ef694a71
6 changed files with 417 additions and 50 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
|||
Thu Apr 24 00:20:01 2008 Yusuke Endoh <mame@tsg.ne.jp>
|
||||
|
||||
* test/ruby/test_settracefunc.rb: add a test for set_trace_func.
|
||||
|
||||
* test/ruby/envutil.rb: move "rubyexec" method from test_rubyoptions.rb.
|
||||
|
||||
* test/ruby/test_rubyoptions.rb: use rubyexec in envutil.rb.
|
||||
|
||||
* test/ruby/test_thread.rb: add tests to achieve over 90% test coverage
|
||||
of thread.c.
|
||||
|
||||
Wed Apr 23 15:28:52 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
|
||||
|
||||
* test/gdbm/test_gdbm.rb (TestGDBM#test_s_open_no_create): failed
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
require "open3"
|
||||
require "timeout"
|
||||
|
||||
module EnvUtil
|
||||
def rubybin
|
||||
unless ENV["RUBYOPT"]
|
||||
|
@ -28,4 +31,42 @@ module EnvUtil
|
|||
end
|
||||
end
|
||||
module_function :rubybin
|
||||
|
||||
LANG_ENVS = %w"LANG LC_ALL LC_CTYPE"
|
||||
def rubyexec(*args)
|
||||
if /(mswin|bccwin|mingw|emx)/ =~ RUBY_PLATFORM
|
||||
flunk("cannot test in win32")
|
||||
return
|
||||
end
|
||||
|
||||
ruby = EnvUtil.rubybin
|
||||
c = "C"
|
||||
env = {}
|
||||
LANG_ENVS.each {|lc| env[lc], ENV[lc] = ENV[lc], c}
|
||||
stdin, stdout, stderr = Open3.popen3(*([ruby] + args))
|
||||
env.each_pair {|lc, v|
|
||||
if v
|
||||
ENV[lc] = v
|
||||
else
|
||||
ENV.delete(lc)
|
||||
end
|
||||
}
|
||||
env = nil
|
||||
Timeout.timeout(10) do
|
||||
yield(stdin, stdout, stderr)
|
||||
end
|
||||
|
||||
ensure
|
||||
env.each_pair {|lc, v|
|
||||
if v
|
||||
ENV[lc] = v
|
||||
else
|
||||
ENV.delete(lc)
|
||||
end
|
||||
} if env
|
||||
stdin .close unless !stdin || stdin .closed?
|
||||
stdout.close unless !stdout || stdout.closed?
|
||||
stderr.close unless !stderr || stderr.closed?
|
||||
end
|
||||
module_function :rubyexec
|
||||
end
|
||||
|
|
|
@ -1,44 +1,12 @@
|
|||
require 'test/unit'
|
||||
|
||||
require 'timeout'
|
||||
require 'tmpdir'
|
||||
require 'tempfile'
|
||||
require 'open3'
|
||||
require_relative 'envutil'
|
||||
|
||||
class TestRubyOptions < Test::Unit::TestCase
|
||||
|
||||
unless /(mswin|bccwin|mingw|emx)/ =~ RUBY_PLATFORM
|
||||
|
||||
LANG_ENVS = %w"LANG LC_ALL LC_CTYPE"
|
||||
def ruby(*args)
|
||||
ruby = EnvUtil.rubybin
|
||||
c = "C"
|
||||
env = {}
|
||||
LANG_ENVS.each {|lc| env[lc], ENV[lc] = ENV[lc], c}
|
||||
stdin, stdout, stderr = Open3.popen3(*([ruby] + args))
|
||||
env.each_pair {|lc, v|
|
||||
if v
|
||||
ENV[lc] = v
|
||||
else
|
||||
ENV.delete(lc)
|
||||
end
|
||||
}
|
||||
env = nil
|
||||
Timeout.timeout(10) do
|
||||
yield(stdin, stdout, stderr)
|
||||
end
|
||||
ensure
|
||||
env.each_pair {|lc, v|
|
||||
if v
|
||||
ENV[lc] = v
|
||||
else
|
||||
ENV.delete(lc)
|
||||
end
|
||||
} if env
|
||||
stdin .close unless !stdin || stdin .closed?
|
||||
stdout.close unless !stdout || stdout.closed?
|
||||
stderr.close unless !stderr || stderr.closed?
|
||||
def ruby(*r, &b)
|
||||
EnvUtil.rubyexec(*r, &b)
|
||||
end
|
||||
|
||||
def test_source_file
|
||||
|
@ -484,13 +452,4 @@ unless /(mswin|bccwin|mingw|emx)/ =~ RUBY_PLATFORM
|
|||
assert_equal('', r.read.chomp)
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
def test_win32
|
||||
flunk("cannot test in win32")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -171,4 +171,8 @@ class TestSetTraceFunc < Test::Unit::TestCase
|
|||
events.shift)
|
||||
assert_equal([], events)
|
||||
end
|
||||
|
||||
def test_invalid_proc
|
||||
assert_raise(TypeError) { set_trace_func(1) }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
require 'test/unit'
|
||||
require 'thread'
|
||||
require_relative 'envutil'
|
||||
|
||||
class TestThread < Test::Unit::TestCase
|
||||
def ruby(*r, &b)
|
||||
EnvUtil.rubyexec(*r, &b)
|
||||
end
|
||||
|
||||
class Thread < ::Thread
|
||||
def self.new(*)
|
||||
th = super
|
||||
|
@ -97,6 +102,335 @@ class TestThread < Test::Unit::TestCase
|
|||
assert_equal("exit.", result[/.*\Z/], '[ruby-dev:30653]')
|
||||
}
|
||||
end
|
||||
|
||||
def test_priority
|
||||
c1 = c2 = 0
|
||||
t1 = Thread.new { loop { c1 += 1 } }
|
||||
t1.priority = -1
|
||||
t2 = Thread.new { loop { c2 += 1 } }
|
||||
t2.priority = -3
|
||||
assert(-1, t1.priority)
|
||||
assert(-3, t2.priority)
|
||||
sleep 0.5
|
||||
t1.kill
|
||||
t2.kill
|
||||
#assert(c1 > c2 * 2, "[ruby-dev:33124]")
|
||||
end
|
||||
|
||||
def test_new
|
||||
assert_raise(ThreadError) do
|
||||
Thread.new
|
||||
end
|
||||
|
||||
t1 = Thread.new { sleep }
|
||||
assert_raise(ThreadError) do
|
||||
t1.instance_eval { initialize { } }
|
||||
end
|
||||
|
||||
t2 = Thread.new(&method(:sleep).to_proc)
|
||||
assert_raise(ThreadError) do
|
||||
t2.instance_eval { initialize { } }
|
||||
end
|
||||
|
||||
ensure
|
||||
t1.kill if t1
|
||||
t2.kill if t2
|
||||
end
|
||||
|
||||
def test_join
|
||||
t = Thread.new { sleep }
|
||||
assert_nil(t.join(0.5))
|
||||
|
||||
ensure
|
||||
t.kill if t
|
||||
end
|
||||
|
||||
def test_join2
|
||||
t1 = Thread.new { sleep(1.5) }
|
||||
t2 = Thread.new do
|
||||
t1.join(1)
|
||||
end
|
||||
t3 = Thread.new do
|
||||
sleep 0.5
|
||||
t1.join
|
||||
end
|
||||
assert_nil(t2.value)
|
||||
assert_equal(t1, t3.value)
|
||||
|
||||
ensure
|
||||
t1.kill if t1
|
||||
t2.kill if t2
|
||||
t3.kill if t3
|
||||
end
|
||||
|
||||
def test_kill_main_thread
|
||||
ruby do |w, r, e|
|
||||
w.puts "p 1"
|
||||
w.puts "Thread.kill Thread.current"
|
||||
w.puts "p 2"
|
||||
w.close
|
||||
assert_equal("1", r.read.chomp)
|
||||
end
|
||||
end
|
||||
|
||||
def test_exit
|
||||
s = 0
|
||||
Thread.new do
|
||||
s += 1
|
||||
Thread.exit
|
||||
s += 2
|
||||
end.join
|
||||
assert_equal(1, s)
|
||||
end
|
||||
|
||||
def test_wakeup
|
||||
s = 0
|
||||
t = Thread.new do
|
||||
s += 1
|
||||
Thread.stop
|
||||
s += 1
|
||||
end
|
||||
sleep 0.5
|
||||
assert_equal(1, s)
|
||||
t.wakeup
|
||||
sleep 0.5
|
||||
assert_equal(2, s)
|
||||
assert_raise(ThreadError) { t.wakeup }
|
||||
|
||||
ensure
|
||||
t.kill if t
|
||||
end
|
||||
|
||||
def test_stop
|
||||
ruby do |w, r, e|
|
||||
w.puts "begin"
|
||||
w.puts " Thread.stop"
|
||||
w.puts " p 1"
|
||||
w.puts "rescue ThreadError"
|
||||
w.puts " p 2"
|
||||
w.puts "end"
|
||||
w.close
|
||||
assert_equal("2", r.read.chomp)
|
||||
end
|
||||
end
|
||||
|
||||
def test_list
|
||||
ruby do |w, r, e|
|
||||
w.puts "t1 = Thread.new { sleep }"
|
||||
w.puts "t2 = Thread.new { loop { } }"
|
||||
w.puts "t3 = Thread.new { }.join"
|
||||
w.puts "p [Thread.current, t1, t2].sort_by {|t| t.object_id }"
|
||||
w.puts "p Thread.list.sort_by {|t| t.object_id }"
|
||||
w.close
|
||||
assert_equal(r.gets, r.gets)
|
||||
end
|
||||
end
|
||||
|
||||
def test_main
|
||||
ruby do |w, r, e|
|
||||
w.puts "p Thread.main == Thread.current"
|
||||
w.puts "Thread.new { p Thread.main == Thread.current }.join"
|
||||
w.close
|
||||
assert_equal("true", r.gets.chomp)
|
||||
assert_equal("false", r.gets.chomp)
|
||||
end
|
||||
end
|
||||
|
||||
def test_abort_on_exception
|
||||
ruby do |w, r, e|
|
||||
w.puts "p Thread.abort_on_exception"
|
||||
w.puts "begin"
|
||||
w.puts " Thread.new { raise }"
|
||||
w.puts " sleep 0.5"
|
||||
w.puts " p 1"
|
||||
w.puts "rescue"
|
||||
w.puts " p 2"
|
||||
w.puts "end"
|
||||
w.close_write
|
||||
assert_equal("false", r.gets.chomp)
|
||||
assert_equal("1", r.gets.chomp)
|
||||
assert_equal("", e.read)
|
||||
end
|
||||
|
||||
ruby do |w, r, e|
|
||||
w.puts "Thread.abort_on_exception = true"
|
||||
w.puts "p Thread.abort_on_exception"
|
||||
w.puts "begin"
|
||||
w.puts " Thread.new { raise }"
|
||||
w.puts " sleep 0.5"
|
||||
w.puts " p 1"
|
||||
w.puts "rescue"
|
||||
w.puts " p 2"
|
||||
w.puts "end"
|
||||
w.close_write
|
||||
assert_equal("true", r.gets.chomp)
|
||||
assert_equal("2", r.gets.chomp)
|
||||
assert_equal("", e.read)
|
||||
end
|
||||
|
||||
ruby('-d') do |w, r, e|
|
||||
w.puts "p Thread.abort_on_exception"
|
||||
w.puts "begin"
|
||||
w.puts " Thread.new { raise }"
|
||||
w.puts " sleep 0.5"
|
||||
w.puts " p 1"
|
||||
w.puts "rescue"
|
||||
w.puts " p 2"
|
||||
w.puts "end"
|
||||
w.close_write
|
||||
assert_equal("false", r.gets.chomp)
|
||||
assert_equal("2", r.gets.chomp)
|
||||
assert_not_equal("", e.read)
|
||||
end
|
||||
|
||||
ruby do |w, r, e|
|
||||
w.puts "p Thread.abort_on_exception"
|
||||
w.puts "begin"
|
||||
w.puts " t = Thread.new { sleep 0.5; raise }"
|
||||
w.puts " t.abort_on_exception = true"
|
||||
w.puts " p t.abort_on_exception"
|
||||
w.puts " sleep 1"
|
||||
w.puts " p 1"
|
||||
w.puts "rescue"
|
||||
w.puts " p 2"
|
||||
w.puts "end"
|
||||
w.close_write
|
||||
assert_equal("false", r.gets.chomp)
|
||||
assert_equal("true", r.gets.chomp)
|
||||
assert_equal("2", r.gets.chomp)
|
||||
assert_equal("", e.read)
|
||||
end
|
||||
end
|
||||
|
||||
def test_status_and_stop_p
|
||||
a = ::Thread.new { raise("die now") }
|
||||
b = Thread.new { Thread.stop }
|
||||
c = Thread.new { Thread.exit }
|
||||
d = Thread.new { sleep }
|
||||
e = Thread.current
|
||||
sleep 0.5
|
||||
d.kill
|
||||
|
||||
assert_equal(nil, a.status)
|
||||
assert_equal("sleep", b.status)
|
||||
assert_equal(false, c.status)
|
||||
assert_match(/^#<TestThread::Thread:.* dead>$/, c.inspect)
|
||||
assert_equal("aborting", d.status)
|
||||
assert_equal("run", e.status)
|
||||
|
||||
assert(a.stop?)
|
||||
assert(b.stop?)
|
||||
assert(c.stop?)
|
||||
assert(!d.stop?)
|
||||
assert(!e.stop?)
|
||||
|
||||
ensure
|
||||
a.kill if a
|
||||
b.kill if b
|
||||
c.kill if c
|
||||
d.kill if d
|
||||
end
|
||||
|
||||
def test_safe_level
|
||||
t = Thread.new { $SAFE = 3; sleep }
|
||||
sleep 0.5
|
||||
assert_equal(0, Thread.current.safe_level)
|
||||
assert_equal(3, t.safe_level)
|
||||
|
||||
ensure
|
||||
t.kill if t
|
||||
end
|
||||
|
||||
def test_thread_local
|
||||
t = Thread.new { sleep }
|
||||
|
||||
assert_equal(false, t.key?(:foo))
|
||||
|
||||
t["foo"] = "foo"
|
||||
t["bar"] = "bar"
|
||||
t["baz"] = "baz"
|
||||
|
||||
assert_equal(true, t.key?(:foo))
|
||||
assert_equal(true, t.key?("foo"))
|
||||
assert_equal(false, t.key?(:qux))
|
||||
assert_equal(false, t.key?("qux"))
|
||||
|
||||
assert_equal([:foo, :bar, :baz], t.keys)
|
||||
|
||||
ensure
|
||||
t.kill if t
|
||||
end
|
||||
|
||||
def test_thread_local_security
|
||||
t = Thread.new { sleep }
|
||||
|
||||
assert_raise(SecurityError) do
|
||||
Thread.new { $SAFE = 4; t[:foo] }.join
|
||||
end
|
||||
|
||||
assert_raise(SecurityError) do
|
||||
Thread.new { $SAFE = 4; t[:foo] = :baz }.join
|
||||
end
|
||||
|
||||
assert_raise(RuntimeError) do
|
||||
Thread.new do
|
||||
Thread.current[:foo] = :bar
|
||||
Thread.current.freeze
|
||||
Thread.current[:foo] = :baz
|
||||
end.join
|
||||
end
|
||||
end
|
||||
|
||||
def test_select_wait
|
||||
assert_nil(IO.select(nil, nil, nil, 1))
|
||||
t = Thread.new do
|
||||
assert_nil(IO.select(nil, nil, nil, nil))
|
||||
end
|
||||
sleep 0.5
|
||||
t.kill
|
||||
end
|
||||
|
||||
def test_mutex_deadlock
|
||||
m = Mutex.new
|
||||
m.synchronize do
|
||||
assert_raise(ThreadError) do
|
||||
m.synchronize do
|
||||
assert(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_mutex_interrupt
|
||||
m = Mutex.new
|
||||
m.lock
|
||||
t = Thread.new do
|
||||
m.lock
|
||||
:foo
|
||||
end
|
||||
sleep 0.5
|
||||
t.kill
|
||||
assert_nil(t.value)
|
||||
end
|
||||
|
||||
def test_mutex_illegal_unlock
|
||||
m = Mutex.new
|
||||
m.lock
|
||||
assert_raise(ThreadError) do
|
||||
Thread.new do
|
||||
m.unlock
|
||||
end.join
|
||||
end
|
||||
end
|
||||
|
||||
def test_recursive_error
|
||||
o = Object.new
|
||||
def o.inspect
|
||||
Thread.current[:__recursive_key__][:inspect] = nil
|
||||
super
|
||||
end
|
||||
assert_raise(TypeError) { [o].inspect }
|
||||
end
|
||||
end
|
||||
|
||||
class TestThreadGroup < Test::Unit::TestCase
|
||||
|
@ -110,25 +444,43 @@ class TestThreadGroup < Test::Unit::TestCase
|
|||
|
||||
def test_frozen_thgroup
|
||||
thgrp = ThreadGroup.new
|
||||
|
||||
t = Thread.new{1}
|
||||
Thread.new{
|
||||
thgrp.add(Thread.current)
|
||||
thgrp.freeze
|
||||
assert_raise(ThreadError) do
|
||||
Thread.new{1}.join
|
||||
end
|
||||
assert_raise(ThreadError) do
|
||||
thgrp.add(t)
|
||||
end
|
||||
assert_raise(ThreadError) do
|
||||
ThreadGroup.new.add Thread.current
|
||||
end
|
||||
}.join
|
||||
t.join
|
||||
end
|
||||
|
||||
def test_enclosed_thgroup
|
||||
thgrp = ThreadGroup.new
|
||||
thgrp.enclose
|
||||
assert_equal(false, thgrp.enclosed?)
|
||||
|
||||
t = Thread.new{1}
|
||||
Thread.new{
|
||||
assert_raise(ThreadError) do
|
||||
thgrp.add(Thread.current)
|
||||
end
|
||||
thgrp.add(Thread.current)
|
||||
thgrp.enclose
|
||||
assert_equal(true, thgrp.enclosed?)
|
||||
assert_nothing_raised do
|
||||
Thread.new{1}.join
|
||||
end
|
||||
assert_raise(ThreadError) do
|
||||
thgrp.add t
|
||||
end
|
||||
assert_raise(ThreadError) do
|
||||
ThreadGroup.new.add Thread.current
|
||||
end
|
||||
}.join
|
||||
t.join
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#define RUBY_VERSION "1.9.0"
|
||||
#define RUBY_RELEASE_DATE "2008-04-23"
|
||||
#define RUBY_RELEASE_DATE "2008-04-24"
|
||||
#define RUBY_VERSION_CODE 190
|
||||
#define RUBY_RELEASE_CODE 20080423
|
||||
#define RUBY_RELEASE_CODE 20080424
|
||||
#define RUBY_PATCHLEVEL 0
|
||||
|
||||
#define RUBY_VERSION_MAJOR 1
|
||||
|
@ -9,7 +9,7 @@
|
|||
#define RUBY_VERSION_TEENY 0
|
||||
#define RUBY_RELEASE_YEAR 2008
|
||||
#define RUBY_RELEASE_MONTH 4
|
||||
#define RUBY_RELEASE_DAY 23
|
||||
#define RUBY_RELEASE_DAY 24
|
||||
|
||||
#ifdef RUBY_EXTERN
|
||||
RUBY_EXTERN const char ruby_version[];
|
||||
|
|
Loading…
Reference in a new issue