Files
metasploit-gs/spec/support/shared/examples/msf/module_manager/cache.rb
T

460 lines
12 KiB
Ruby
Raw Normal View History

2015-12-31 16:56:13 -06:00
RSpec.shared_examples_for 'Msf::ModuleManager::Cache' do
2013-09-30 13:47:53 -05:00
let(:parent_path) do
parent_pathname.to_path
end
let(:parent_pathname) do
Metasploit::Framework.root.join('modules')
end
let(:reference_name) do
'windows/smb/ms08_067_netapi'
end
let(:type) do
'exploit'
end
let(:path) do
pathname.to_path
end
let(:pathname) do
parent_pathname.join(
'exploits',
"#{reference_name}.rb"
)
end
let(:pathname_modification_time) do
pathname.mtime
end
context '#cache_empty?' do
subject(:cache_empty?) do
module_manager.cache_empty?
end
2015-12-31 16:56:13 -06:00
before(:example) do
2013-09-30 13:47:53 -05:00
module_manager.send(:module_info_by_path=, module_info_by_path)
end
context 'with empty' do
let(:module_info_by_path) do
{}
end
2015-10-21 09:23:22 -05:00
it { is_expected.to be_truthy }
2013-09-30 13:47:53 -05:00
end
context 'without empty' do
let(:module_info_by_path) do
{
'path/to/module' => {}
}
end
2015-10-21 09:23:22 -05:00
it { is_expected.to be_falsey }
2013-09-30 13:47:53 -05:00
end
end
context '#cache_in_memory' do
def cache_in_memory
module_manager.cache_in_memory(
class_or_module,
:path => path,
:reference_name => reference_name,
:type => type
)
end
def module_info_by_path
module_manager.send(:module_info_by_path)
end
let(:class_or_module) do
double('Class<Msf::Module> or Module', :parent => namespace_module)
end
let(:namespace_module) do
double('Msf::Modules::Namespace', :parent_path => parent_path)
end
context 'with existing :path' do
it 'should update module_info_by_path' do
expect {
cache_in_memory
}.to change { module_info_by_path }
end
context 'module_info_by_path' do
subject(:module_info_by_path) do
module_manager.send(:module_info_by_path)
end
2015-12-31 16:56:13 -06:00
before(:example) do
2013-09-30 13:47:53 -05:00
cache_in_memory
end
it 'should have entry for path' do
2015-10-20 14:37:18 -05:00
expect(module_info_by_path[path]).to be_a Hash
2013-09-30 13:47:53 -05:00
end
context 'value' do
subject(:value) do
module_info_by_path[path]
end
it 'should have modification time of :path option for :modification_time' do
2015-10-20 11:30:38 -05:00
expect(value[:modification_time]).to eq pathname_modification_time
2013-09-30 13:47:53 -05:00
end
2013-04-15 13:08:12 -05:00
2013-09-30 13:47:53 -05:00
it 'should have parent path from namespace module for :parent_path' do
2015-10-20 11:30:38 -05:00
expect(value[:parent_path]).to eq namespace_module.parent_path
2013-09-30 13:47:53 -05:00
end
2013-04-15 13:08:12 -05:00
2013-09-30 13:47:53 -05:00
it 'should use :reference_name option' do
2015-10-20 11:30:38 -05:00
expect(value[:reference_name]).to eq reference_name
2013-09-30 13:47:53 -05:00
end
2013-04-15 13:08:12 -05:00
2013-09-30 13:47:53 -05:00
it 'should use :type option' do
2015-10-20 11:30:38 -05:00
expect(value[:type]).to eq type
2013-09-30 13:47:53 -05:00
end
end
end
end
2013-04-15 13:08:12 -05:00
2013-09-30 13:47:53 -05:00
context 'without existing :path' do
let(:path) do
'non/existent/path'
end
2013-04-15 13:08:12 -05:00
2013-09-30 13:47:53 -05:00
it 'should not raise error' do
expect {
cache_in_memory
}.to_not raise_error
end
2013-04-15 13:08:12 -05:00
2013-09-30 13:47:53 -05:00
it 'should not update module_info_by_path' do
expect {
cache_in_memory
}.to_not change { module_info_by_path }
end
end
end
context '#load_cached_module' do
subject(:load_cached_module) do
module_manager.load_cached_module(type, reference_name)
end
2015-12-31 16:56:13 -06:00
before(:example) do
2013-09-30 13:47:53 -05:00
module_manager.send(:module_info_by_path=, module_info_by_path)
end
context 'with module info in cache' do
2014-10-29 15:50:47 -05:00
include_context 'Metasploit::Framework::Spec::Constants cleaner'
2013-09-30 13:47:53 -05:00
let(:module_info_by_path) do
{
'path/to/module' => {
:parent_path => parent_path,
:reference_name => reference_name,
:type => type
}
}
end
2013-04-15 13:08:12 -05:00
2013-09-30 13:47:53 -05:00
it 'should enumerate loaders until if it find the one where loadable?(parent_path) is true' do
2017-03-27 15:36:47 -05:00
# Only the first one gets it since it finds the module
loader = module_manager.send(:loaders).first
expect(loader).to receive(:loadable?).with(parent_path).and_call_original
2013-04-15 13:08:12 -05:00
2013-09-30 13:47:53 -05:00
load_cached_module
end
2013-04-15 13:08:12 -05:00
2013-09-30 13:47:53 -05:00
it 'should force load using #load_module on the loader' do
2015-10-20 15:13:50 -05:00
expect_any_instance_of(Msf::Modules::Loader::Directory).to receive(
2013-09-30 13:47:53 -05:00
:load_module
).with(
parent_path,
type,
reference_name,
:force => true
).and_call_original
load_cached_module
end
context 'return from load_module' do
2015-12-31 16:56:13 -06:00
before(:example) do
2017-03-27 15:36:47 -05:00
# Only the first one gets it since it finds the module
loader = module_manager.send(:loaders).first
expect(loader).to receive(:load_module).and_return(module_loaded)
2013-09-30 13:47:53 -05:00
end
context 'with false' do
let(:module_loaded) do
false
end
2013-04-15 13:08:12 -05:00
2015-10-21 09:23:22 -05:00
it { is_expected.to be_falsey }
2013-09-30 13:47:53 -05:00
end
2013-04-15 13:08:12 -05:00
2013-09-30 13:47:53 -05:00
context 'with true' do
let(:module_loaded) do
true
end
2015-10-21 09:23:22 -05:00
it { is_expected.to be_truthy }
2013-09-30 13:47:53 -05:00
end
end
end
2013-04-15 13:08:12 -05:00
2013-09-30 13:47:53 -05:00
context 'without module info in cache' do
let(:module_info_by_path) do
{}
end
2015-10-21 09:23:22 -05:00
it { is_expected.to be_falsey }
2013-09-30 13:47:53 -05:00
end
end
context '#refresh_cache_from_module_files' do
2015-12-31 16:56:13 -06:00
before(:example) do
allow(module_manager).to receive(:framework_migrated?).and_return(framework_migrated?)
2013-09-30 13:47:53 -05:00
end
context 'with framework migrated' do
let(:framework_migrated?) do
true
end
context 'with module argument' do
def refresh_cache_from_module_files
module_manager.refresh_cache_from_module_files(module_class_or_instance)
end
let(:module_class_or_instance) do
Class.new(Msf::Module)
end
it 'should update database and then update in-memory cache from the database for the given module_class_or_instance' do
2015-10-20 12:40:33 -05:00
expect(framework.db).to receive(:update_module_details).with(module_class_or_instance).ordered
expect(module_manager).to receive(:refresh_cache_from_database).ordered
2013-09-30 13:47:53 -05:00
refresh_cache_from_module_files
end
end
context 'without module argument' do
def refresh_cache_from_module_files
module_manager.refresh_cache_from_module_files
end
it 'should update database and then update in-memory cache from the database for all modules' do
2015-10-20 12:40:33 -05:00
expect(framework.db).to receive(:update_all_module_details).ordered
expect(module_manager).to receive(:refresh_cache_from_database)
2013-09-30 13:47:53 -05:00
refresh_cache_from_module_files
end
end
end
context 'without framework migrated' do
def refresh_cache_from_module_files
module_manager.refresh_cache_from_module_files
end
let(:framework_migrated?) do
false
end
it 'should not call Msf::DBManager#update_module_details' do
expect(framework.db).not_to receive(:update_module_details)
2013-09-30 13:47:53 -05:00
refresh_cache_from_module_files
end
2013-04-15 13:08:12 -05:00
2013-09-30 13:47:53 -05:00
it 'should not call Msf::DBManager#update_all_module_details' do
expect(framework.db).not_to receive(:update_all_module_details)
2013-09-30 13:47:53 -05:00
refresh_cache_from_module_files
end
it 'should not call #refresh_cache_from_database' do
expect(module_manager).not_to receive(:refresh_cache_from_database)
2013-09-30 13:47:53 -05:00
refresh_cache_from_module_files
end
end
end
context '#refresh_cache_from_database' do
def refresh_cache_from_database
module_manager.refresh_cache_from_database
end
it 'should call #module_info_by_path_from_database!' do
2015-10-20 12:40:33 -05:00
expect(module_manager).to receive(:module_info_by_path_from_database!)
2013-09-30 13:47:53 -05:00
refresh_cache_from_database
end
end
context '#framework_migrated?' do
subject(:framework_migrated?) do
module_manager.send(:framework_migrated?)
end
context 'with framework database' do
2015-12-31 16:56:13 -06:00
before(:example) do
2015-10-20 13:45:31 -05:00
expect(framework.db).to receive(:migrated).and_return(migrated)
2013-09-30 13:47:53 -05:00
end
context 'with migrated' do
let(:migrated) do
true
end
2015-10-21 09:23:22 -05:00
it { is_expected.to be_truthy }
2013-09-30 13:47:53 -05:00
end
context 'without migrated' do
let(:migrated) do
false
end
2015-10-21 09:23:22 -05:00
it { is_expected.to be_falsey }
2013-09-30 13:47:53 -05:00
end
end
context 'without framework database' do
2015-12-31 16:56:13 -06:00
before(:example) do
2015-10-20 13:45:31 -05:00
expect(framework).to receive(:db).and_return(nil)
2013-09-30 13:47:53 -05:00
end
2015-10-21 09:23:22 -05:00
it { is_expected.to be_falsey }
2013-09-30 13:47:53 -05:00
end
end
context '#module_info_by_path' do
2014-09-08 00:57:51 -05:00
it 'should have protected method module_info_by_path' do
2015-10-20 14:37:18 -05:00
expect(subject.respond_to?(:module_info_by_path, true)).to be_truthy
2014-09-08 00:57:51 -05:00
end
2013-09-30 13:47:53 -05:00
end
context '#module_info_by_path=' do
2014-09-08 00:57:51 -05:00
it 'should have protected method module_info_by_path=' do
2015-10-20 14:37:18 -05:00
expect(subject.respond_to?(:module_info_by_path=, true)).to be_truthy
2014-09-08 00:57:51 -05:00
end
2013-09-30 13:47:53 -05:00
end
context '#module_info_by_path_from_database!' do
def module_info_by_path
module_manager.send(:module_info_by_path)
end
def module_info_by_path_from_database!
module_manager.send(:module_info_by_path_from_database!)
end
2015-12-31 16:56:13 -06:00
before(:example) do
allow(module_manager).to receive(:framework_migrated?).and_return(framework_migrated?)
2013-09-30 13:47:53 -05:00
end
context 'with framework migrated' do
let(:framework_migrated?) do
true
end
2013-04-26 13:14:38 -05:00
it 'should use ActiveRecord::Batches#find_each to enumerate Mdm::Module::Details in batches' do
2015-10-20 12:40:33 -05:00
expect(Mdm::Module::Detail).to receive(:find_each)
2013-09-30 13:47:53 -05:00
module_info_by_path_from_database!
end
context 'with database cache' do
#
# Let!s (let + before(:each))
#
let!(:mdm_module_detail) do
FactoryGirl.create(:mdm_module_detail,
:file => path,
:mtype => type,
:mtime => pathname.mtime,
:refname => reference_name
)
end
it 'should create cache entry for path' do
module_info_by_path_from_database!
2015-10-20 14:37:18 -05:00
expect(module_info_by_path).to have_key(path)
2013-09-30 13:47:53 -05:00
end
context 'cache entry' do
subject(:cache_entry) do
module_info_by_path[path]
end
2015-12-31 16:56:13 -06:00
before(:example) do
2013-09-30 13:47:53 -05:00
module_info_by_path_from_database!
end
it { expect(subject[:modification_time]).to be_within(1.second).of(pathname_modification_time) }
it { expect(subject[:parent_path]).to eq(parent_path) }
it { expect(subject[:reference_name]).to eq(reference_name) }
it { expect(subject[:type]).to eq(type) }
2013-09-30 13:47:53 -05:00
end
context 'typed module set' do
let(:typed_module_set) do
module_manager.module_set(type)
end
context 'with reference_name' do
2015-12-31 16:56:13 -06:00
before(:example) do
2013-09-30 13:47:53 -05:00
typed_module_set[reference_name] = double('Msf::Module')
end
it 'should not change reference_name value' do
expect {
module_info_by_path_from_database!
}.to_not change {
typed_module_set[reference_name]
}
end
end
context 'without reference_name' do
it 'should set reference_name value to Msf::SymbolicModule' do
module_info_by_path_from_database!
# have to use fetch because [] will trigger de-symbolization and
# instantiation.
2015-10-20 11:30:38 -05:00
expect(typed_module_set.fetch(reference_name)).to eq Msf::SymbolicModule
2013-09-30 13:47:53 -05:00
end
end
end
end
end
2013-04-15 13:08:12 -05:00
2013-09-30 13:47:53 -05:00
context 'without framework migrated' do
let(:framework_migrated?) do
false
2013-04-15 13:08:12 -05:00
end
2013-09-30 13:47:53 -05:00
it 'should reset #module_info_by_path' do
# pre-fill module_info_by_path so change can be detected
module_manager.send(:module_info_by_path=, double('In-memory Cache'))
module_info_by_path_from_database!
2015-10-20 14:37:18 -05:00
expect(module_info_by_path).to be_empty
2013-09-30 13:47:53 -05:00
end
end
end
2014-08-26 15:24:08 -05:00
end