parent
96990fdc02
commit
097aa330e1
1
Rakefile
1
Rakefile
|
@ -10,4 +10,5 @@ require 'metasploit/framework/spec/untested_payloads'
|
||||||
Metasploit::Framework::Require.optionally_active_record_railtie
|
Metasploit::Framework::Require.optionally_active_record_railtie
|
||||||
|
|
||||||
Metasploit::Framework::Application.load_tasks
|
Metasploit::Framework::Application.load_tasks
|
||||||
|
Metasploit::Framework::Spec::Threads::Suite.define_task
|
||||||
Metasploit::Framework::Spec::UntestedPayloads.define_task
|
Metasploit::Framework::Spec::UntestedPayloads.define_task
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
require 'metasploit/framework/spec/threads/suite'
|
||||||
|
|
||||||
|
original_thread_new = Thread.method(:new)
|
||||||
|
|
||||||
|
# Patches `Thread.new` so that if logs `caller` so thread leaks can be traced
|
||||||
|
Thread.define_singleton_method(:new) { |*args, &block|
|
||||||
|
lines = ['BEGIN Thread.new caller']
|
||||||
|
|
||||||
|
caller.each do |frame|
|
||||||
|
lines << " #{frame}"
|
||||||
|
end
|
||||||
|
|
||||||
|
lines << 'END Thread.new caller'
|
||||||
|
|
||||||
|
Metasploit::Framework::Spec::Threads::Suite::LOG_PATHNAME.parent.mkpath
|
||||||
|
|
||||||
|
Metasploit::Framework::Spec::Threads::Suite::LOG_PATHNAME.open('a') { |f|
|
||||||
|
# single puts so threads can't write in between each other.
|
||||||
|
f.puts lines.join("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
original_thread_new.call(*args, &block)
|
||||||
|
}
|
|
@ -1,35 +1,65 @@
|
||||||
module Metasploit::Framework::Spec::Threads::Suite
|
require 'pathname'
|
||||||
#
|
|
||||||
# CONSTANTS
|
|
||||||
#
|
|
||||||
|
|
||||||
EXPECTED_THREAD_COUNT_BEFORE_SUITE = 1
|
# @note needs to use explicit nesting. so this file can be loaded directly without loading 'metasploit/framework' which
|
||||||
|
# allows for faster loading of rake tasks.
|
||||||
|
module Metasploit
|
||||||
|
module Framework
|
||||||
|
module Spec
|
||||||
|
module Threads
|
||||||
|
module Suite
|
||||||
|
#
|
||||||
|
# CONSTANTS
|
||||||
|
#
|
||||||
|
|
||||||
#
|
# Number of allowed threads when threads are counted in `before(:suite)`
|
||||||
# Module Methods
|
EXPECTED_THREAD_COUNT_BEFORE_SUITE = 1
|
||||||
#
|
# `caller` for all Thread.new calls
|
||||||
|
LOG_PATHNAME = Pathname.new('log/metasploit/framework/spec/threads/suite.log')
|
||||||
|
|
||||||
# Configures `before(:suite)` and `after(:suite)` callback to detect thread leaks.
|
#
|
||||||
#
|
# Module Methods
|
||||||
# @return [void]
|
#
|
||||||
def self.configure!
|
|
||||||
unless @configured
|
|
||||||
RSpec.configure do |config|
|
|
||||||
config.before(:suite) do
|
|
||||||
thread_count = Thread.list.count
|
|
||||||
|
|
||||||
expect(thread_count).to(
|
# Configures `before(:suite)` and `after(:suite)` callback to detect thread leaks.
|
||||||
(be <= EXPECTED_THREAD_COUNT_BEFORE_SUITE),
|
#
|
||||||
"#{thread_count} #{'thread'.pluralize(thread_count)} exist(s) when " \
|
# @return [void]
|
||||||
"only #{EXPECTED_THREAD_COUNT_BEFORE_SUITE} #{'thread'.pluralize(EXPECTED_THREAD_COUNT_BEFORE_SUITE)} " \
|
def self.configure!
|
||||||
"expected before suite runs"
|
unless @configured
|
||||||
)
|
RSpec.configure do |config|
|
||||||
|
config.before(:suite) do
|
||||||
|
thread_count = Thread.list.count
|
||||||
|
|
||||||
|
# check with if first so that error message can be constructed lazily
|
||||||
|
if thread_count > EXPECTED_THREAD_COUNT_BEFORE_SUITE
|
||||||
|
log = LOG_PATHNAME.read()
|
||||||
|
|
||||||
|
raise RuntimeError,
|
||||||
|
"#{thread_count} #{'thread'.pluralize(thread_count)} exist(s) when " \
|
||||||
|
"only #{EXPECTED_THREAD_COUNT_BEFORE_SUITE} " \
|
||||||
|
"#{'thread'.pluralize(EXPECTED_THREAD_COUNT_BEFORE_SUITE)} expected before suite runs:\n#{log}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@configured = true
|
||||||
|
end
|
||||||
|
|
||||||
|
@configured
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.define_task
|
||||||
|
Rake::Task.define_task('metasploit:framework:spec:threads:suite') do
|
||||||
|
parent_pathname = Pathname.new(__FILE__).parent
|
||||||
|
threads_logger_pathname = parent_pathname.join('logger')
|
||||||
|
load_pathname = parent_pathname.parent.parent.parent.parent.expand_path
|
||||||
|
|
||||||
|
ENV['RUBYOPT'] = "-I#{load_pathname} -r#{threads_logger_pathname} #{ENV['RUBYOPT']}"
|
||||||
|
end
|
||||||
|
|
||||||
|
Rake::Task.define_task(spec: 'metasploit:framework:spec:threads:suite')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@configured = true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@configured
|
|
||||||
end
|
end
|
||||||
end
|
end
|
Loading…
Reference in New Issue