=======

TimeoutInterruptSingleton created for helper methods like setup and so on.

TimeoutInterrupt#timeout and TimeoutInterrupt.timeout are stubs for calling timeout of singleton-class.

Scopeable
=========

`TimeoutInterrupt.timeout` should be scopeable now.
`TimeoutInterrupt.timeout` without args will check timeouts and will raise the next timed out timeout,
needed for scopes and if many time outs at the same time occurs.
This commit is contained in:
Denis Knauf 2013-03-07 12:30:07 +01:00
parent 7608c98054
commit 6f57bb4223
3 changed files with 230 additions and 78 deletions

View file

@ -11,70 +11,145 @@ class TestRubyTimeoutInterrupt < Test::Unit::TestCase
end
def assert_no_defined_timeout_yet
assert TimeoutInterrupt.timeouts.empty?, "For testing, no timeout should be defined, yet!"
assert TimeoutInterruptSingleton.timeouts.empty?, "For testing, no timeout should be defined, yet!"
end
should "not interrupt a long blocking call with the old Timeout" do
time = Benchmark.realtime do
begin
TimeoutInterrupt.timeout(5) do
Timeout.timeout(1) do
def print_timeouts pre
puts "#{pre}: < #{TimeoutInterruptSingleton.timeouts.map {|k,(a,_b,_e)| "#{k.inspect}: #{a.strftime '%H:%M:%S'} (#{a-Time.now})" }.join ', '} >"
end
# For testing raising scoped Timeout.
class TimeoutError < Exception
end
# For testing raising scoped TimeoutInterrupt.
class TimeoutInterruptError < Exception
end
context "Long really blocking calls" do
should "not be interrupted by the old Timeout" do
time = Benchmark.realtime do
assert_nothing_raised TimeoutError, "Unexpected time out. Your Ruby implementation can time out with old Timeout? You need not TimeoutInterrupt. But it is ok. You can ignore this Error. :)" do
assert_raise TimeoutInterruptError, "Ohoh. TimeoutInterrupt should be raised." do
TimeoutInterrupt.timeout 5, TimeoutInterruptError do
Timeout.timeout 1, TimeoutError do
blocking
assert false, "Should be unreachable!"
end
end
end
end
end
assert 3 < time, "Did timeout!"
end
should "be interrupted by the new TimeoutInterrupt" do
time = Benchmark.realtime do
assert_raise TimeoutInterrupt::Error, "It should be timed out, why it did not raise TimeoutInterrupt::Error?" do
TimeoutInterrupt.timeout 1 do
blocking
assert false, "Should be unreachable!"
end
end
rescue Timeout::Error
:ok
end
assert 3 > time, "Did not interrupt."
end
assert 3 < time, "Did timeout!"
end
should "interrupt a long blocking call with the new TimeoutInterrupt" do
time = Benchmark.realtime do
begin
TimeoutInterrupt.timeout(1) do
blocking
should "interrupt scoped timeout, but not time out the outer timeout" do
assert_no_defined_timeout_yet
assert_raise TimeoutInterruptError, "It should be timed out, why it did not raise TimeoutInterruptError?" do
assert_nothing_raised Timeout::Error, "Oh, outer timeout was timed out. Your machine must be slow, or there is a bug" do
TimeoutInterrupt.timeout 10 do
TimeoutInterrupt.timeout 1, TimeoutInterruptError do
Kernel.sleep 2
end
assert false, "Should be unreachable!"
end
rescue Timeout::Error
:ok
end
end
assert 3 > time, "Did not interrupt."
end
should "interrupt scoped timeout, but not outer timeout" do
assert_no_defined_timeout_yet
begin
TimeoutInterrupt.timeout(10) do
TimeoutInterrupt.timeout(1) do
Kernel.sleep 2
end
assert false, "Should be unreachable!"
end
rescue Timeout::Error
:ok
end
assert TimeoutInterrupt.timeouts.empty?, "There are timeouts defined, yet!"
assert TimeoutInterruptSingleton.timeouts.empty?, "There are timeouts defined, yet!"
end
should "clear timeouts, if not timed out, too." do
assert_no_defined_timeout_yet
TimeoutInterrupt.timeout(10) {}
assert TimeoutInterrupt.timeouts.empty?, "There are timeouts defined, yet!"
assert TimeoutInterruptSingleton.timeouts.empty?, "There are timeouts defined, yet!"
end
should "return a Proc if now block given, but do not create a timeout." do
assert_no_defined_timeout_yet
assert TimeoutInterrupt.timeout(10).kind_of?( Proc), "Did not return a Proc."
class CustomException <Exception
end
should "run a returned Proc with given timeout." do
assert_no_defined_timeout_yet
to = TimeoutInterrupt.timeout(10)
called = false
to.call { called = true }
assert called, "Did not called."
should "raise custom exception." do
assert_raise CustomException, "Custom exceptions do not work." do
TimeoutInterrupt.timeout 1, CustomException do
sleep 2
end
end
end
context "A prepared timeout (Proc)" do
should "be returned by calling timeout without a block" do
assert_no_defined_timeout_yet
assert TimeoutInterrupt.timeout(10).kind_of?( Proc), "Did not return a Proc."
end
should "run with once given timeout" do
assert_no_defined_timeout_yet
to = TimeoutInterrupt.timeout 10
called = false
to.call { called = true }
assert called, "Did not called."
end
should "raise custom exception" do
assert_raise CustomException, "Custom exceptions do not work." do
prepared = TimeoutInterrupt.timeout 1, CustomException
prepared.call { sleep 2 }
end
end
should "not be scopeable, without manualy setup after rescue and 2 time outs at once" do
prepared = TimeoutInterrupt.timeout 1
assert_no_defined_timeout_yet
called = false
prepared.call do
assert_raise TimeoutInterrupt::Error, 'It should time out after one second, but it did not.' do
prepared.call { 2; sleep 2 }
end
called = true
end
assert called, "It's true, it should be called, also if not expected."
end
should "be scopeable, with manualy setup after rescue, also if 2 time outs at once." do
prepared = TimeoutInterrupt.timeout 1
assert_no_defined_timeout_yet
prepared.call do
assert_raise TimeoutInterrupt::Error, 'It should time out after one second, but it did not.' do
prepared.call { sleep 2 }
end
assert_raise TimeoutInterrupt::Error, 'Manualy called timeout setup did not raise.' do
TimeoutInterrupt.timeout
end
assert true, "Should never be reached."
end
end
end
class IncludeModuleTest
include TimeoutInterrupt
def please_timeout after
timeout after do
sleep after+10
end
end
end
context "Included module" do
should "provide timeout too" do
assert_raise TimeoutInterrupt::Error, "Included timeout can not be used?" do
IncludeModuleTest.new.please_timeout 2
end
end
end
end