101 lines
3.0 KiB
Ruby
101 lines
3.0 KiB
Ruby
require 'msf/core/modules'
|
|
|
|
# Monitor constants created by module loading to ensure that the loads in one example don't interfere with the
|
|
# assertions in another example.
|
|
module Metasploit::Framework::Spec::Constants
|
|
extend ActiveSupport::Autoload
|
|
|
|
autoload :Each
|
|
autoload :Suite
|
|
|
|
#
|
|
# CONSTANTS
|
|
#
|
|
|
|
# Regex parsing loaded module constants
|
|
LOADED_MODULE_CHILD_CONSTANT_REGEXP = /^Mod(?<unpacked_full_name>[0-9a-f]+)$/
|
|
# The parent namespace child_constant_name that can have children added when loading modules.
|
|
PARENT_CONSTANT = Msf::Modules
|
|
# Constant names under {PARENT_CONSTANT} that can persist between specs because they are part of the loader library
|
|
# and not dynamically loaded code
|
|
PERSISTENT_CHILD_CONSTANT_NAMES = %w{
|
|
Error
|
|
External
|
|
Loader
|
|
MetasploitClassCompatibilityError
|
|
Namespace
|
|
VersionCompatibilityError
|
|
}.map(&:to_sym)
|
|
|
|
# Cleans child constants from {PARENT_CONSTANT}.
|
|
#
|
|
# @return [true] if there were leaked constants that were cleaned.
|
|
# @return [false] if there were no leaked constants.
|
|
# @see each
|
|
def self.clean
|
|
count = each do |child_name|
|
|
PARENT_CONSTANT.send(:remove_const, child_name)
|
|
end
|
|
|
|
count != 0
|
|
end
|
|
|
|
# Adds actions to `spec` task so that `rake spec` fails if any of the following:
|
|
#
|
|
# # `log/leaked-constants.log` exists after printing out the leaked constants.
|
|
# # Each.configured! is unnecessary in `spec/spec_helper.rb` and should be removed.
|
|
#
|
|
# @return [void]
|
|
def self.define_task
|
|
Suite.define_task
|
|
# After Suite as Suite will kill for leaks before Each say it cleaned no leaks in case there are leaks in an
|
|
# `after(:all)` that {Each} won't catch in its `after(:each)` checks.
|
|
Each.define_task
|
|
end
|
|
|
|
# Yields each child_constant_name under {PARENT_CONSTANT}.
|
|
#
|
|
# @yield [child_name]
|
|
# @yieldparam child_name [Symbol] name of child_constant_name relative to {PARENT_CONSTANT}.
|
|
# @yieldreturn [void]
|
|
# @return [Integer] count
|
|
def self.each
|
|
inherit = false
|
|
count = 0
|
|
|
|
child_constant_names = PARENT_CONSTANT.constants(inherit)
|
|
|
|
child_constant_names.each do |child_constant_name|
|
|
unless PERSISTENT_CHILD_CONSTANT_NAMES.include? child_constant_name
|
|
count += 1
|
|
yield child_constant_name
|
|
end
|
|
end
|
|
|
|
count
|
|
end
|
|
|
|
# The module full name for `child_constant_name`
|
|
#
|
|
# @param child_constant_name [String] the name of a child constant_name under {PARENT_CONSTANT}.
|
|
# @return [String] full module name used to load `child_constant_name`.
|
|
# @return [nil] if `child_constant_name` does not correspond to a loaded module.
|
|
def self.full_name(child_constant_name)
|
|
full_name = nil
|
|
|
|
match = LOADED_MODULE_CHILD_CONSTANT_REGEXP.match(child_constant_name)
|
|
|
|
if match
|
|
potential_full_name = [match[:unpacked_full_name]].pack('H*')
|
|
|
|
module_type, _reference_name = potential_full_name.split('/', 2)
|
|
|
|
if Msf::MODULE_TYPES.include? module_type
|
|
full_name = potential_full_name
|
|
end
|
|
end
|
|
|
|
full_name
|
|
end
|
|
end
|