mirror of
https://github.com/zammad/zammad
synced 2026-05-24 09:48:36 +00:00
59 lines
2 KiB
Ruby
59 lines
2 KiB
Ruby
# Copyright (C) 2012-2026 Zammad Foundation, https://zammad-foundation.org/
|
|
|
|
module ThreadsHelper
|
|
# Ensure that any new threads which might be spawned by the block will be cleaned up
|
|
# to not interfere with any subsequent tests.
|
|
def ensure_threads_exited()
|
|
initial_threads = Thread.list
|
|
yield
|
|
ensure
|
|
superfluous_threads = -> { Thread.list - initial_threads }
|
|
|
|
# Keep going until no more changes are needed to catch threads spawned in between.
|
|
3.times do
|
|
superfluous_threads.call.each do |t|
|
|
t.kill
|
|
t.join # From `Timeout.timeout`: make sure thread is dead.
|
|
end
|
|
break if superfluous_threads.call.none?
|
|
|
|
sleep 1 # Wait a bit for stuff to settle before trying again.
|
|
end
|
|
|
|
if superfluous_threads.call.any?
|
|
superfluous_threads.call.each do |thread|
|
|
warn "Error: found a superfluous thread after clean-up: #{thread}"
|
|
warn "Backtrace: #{thread.backtrace.join("\n")}"
|
|
end
|
|
raise 'Superfluous threads found after clean-up.'
|
|
end
|
|
|
|
# Sometimes connections are not checked back in after thread is killed
|
|
# This recovers connections from the workers
|
|
ActiveRecord::Base.connection_pool.reap
|
|
end
|
|
|
|
# Thread control loops usually run forever. This method can test that they were started.
|
|
def ensure_block_keeps_running(timeout: 2.seconds, &)
|
|
# Stop after timeout and return true if everything was ok.
|
|
# Suppress the Rails logger as its exception may rescue our TimeoutErrors, causing failures here.
|
|
Rails.logger.silence do
|
|
Timeout.timeout(timeout, &)
|
|
end
|
|
raise 'Process ended unexpectedly.'
|
|
rescue SystemExit
|
|
# Convert SystemExit to a RuntimeError as otherwise rspec will shut down without an error.
|
|
raise 'Process tried to shut down unexpectedly.'
|
|
rescue Timeout::Error
|
|
# Default case: process started fine and kept running, interrupted by timeout.
|
|
true
|
|
end
|
|
end
|
|
|
|
RSpec.configure do |config|
|
|
config.include ThreadsHelper
|
|
|
|
config.around(:each, :ensure_threads_exited) do |example|
|
|
ensure_threads_exited { example.run }
|
|
end
|
|
end
|