summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authormame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-04-23 15:22:13 +0000
committermame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-04-23 15:22:13 +0000
commitf7ef694a712d8deccfba67a4860b0272e335f17a (patch)
treede1333bc139328e336cb974ab6f33644a72b97ea /test
parentc0d8e6cbf9d7e068e98ff2053bff18ee13e338df (diff)
* 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
Diffstat (limited to 'test')
-rw-r--r--test/ruby/envutil.rb41
-rw-r--r--test/ruby/test_rubyoptions.rb45
-rw-r--r--test/ruby/test_settracefunc.rb4
-rw-r--r--test/ruby/test_thread.rb360
4 files changed, 403 insertions, 47 deletions
diff --git a/test/ruby/envutil.rb b/test/ruby/envutil.rb
index bbcab83d06..37efdde84e 100644
--- a/test/ruby/envutil.rb
+++ b/test/ruby/envutil.rb
@@ -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
diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb
index 316f313a2c..3304a17ebf 100644
--- a/test/ruby/test_rubyoptions.rb
+++ b/test/ruby/test_rubyoptions.rb
@@ -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
diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb
index 5ec450cb6d..1f260e003c 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -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
diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb
index feebd99f13..b03b60b72a 100644
--- a/test/ruby/test_thread.rb
+++ b/test/ruby/test_thread.rb
@@ -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