diff options
Diffstat (limited to 'spec/mspec/lib/mspec/runner/actions/timeout.rb')
-rw-r--r-- | spec/mspec/lib/mspec/runner/actions/timeout.rb | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/spec/mspec/lib/mspec/runner/actions/timeout.rb b/spec/mspec/lib/mspec/runner/actions/timeout.rb new file mode 100644 index 0000000000..9090efbe44 --- /dev/null +++ b/spec/mspec/lib/mspec/runner/actions/timeout.rb @@ -0,0 +1,60 @@ +class TimeoutAction + def initialize(timeout) + @timeout = timeout + @queue = Queue.new + @started = now + end + + def register + MSpec.register :start, self + MSpec.register :before, self + MSpec.register :finish, self + end + + private def now + Process.clock_gettime(Process::CLOCK_MONOTONIC) + end + + private def fetch_item + @queue.pop(true) + rescue ThreadError + nil + end + + def start + @thread = Thread.new do + loop do + if action = fetch_item + action.call + else + wakeup_at = @started + @timeout + left = wakeup_at - now + sleep left if left > 0 + Thread.pass # Let the main thread run + + if @queue.empty? + elapsed = now - @started + if elapsed > @timeout + STDERR.puts "\n#{@current_state.description}" + STDERR.flush + abort "Example took #{now - @started}s, which is longer than the timeout of #{@timeout}s" + end + end + end + end + end + end + + def before(state=nil) + time = now + @queue << -> do + @current_state = state + @started = time + end + end + + def finish + @thread.kill + @thread.join + end +end |