Files
metasploit-gs/spec/support/shared/examples/msf/db_manager/migration.rb
T
Luke Imhoff 89bd5b4791 Reset column information after running migrations
[#50179803]
[SeeRM #7967]
[SeeRM #7870]

Because metasploit-framework runs migrations with the same process and
with the same connection as it later accesses the database, the column
information can become cached prematurely and be incorrect by the end of
the migrations.  Fix the bad cache by automatically resetting the column
information for all model classes after the migrations have run.
2013-05-20 13:08:07 -05:00

143 lines
3.0 KiB
Ruby

shared_examples_for 'Msf::DBManager::Migration' do
it { should be_a Msf::DBManager::Migration }
context '#migrate' do
def migrate
db_manager.migrate
end
it 'should create a connection' do
ActiveRecord::Base.connection_pool.should_receive(:with_connection).twice
migrate
end
it 'should call ActiveRecord::Migrator.migrate' do
ActiveRecord::Migrator.should_receive(:migrate).with(
ActiveRecord::Migrator.migrations_paths
)
migrate
end
it 'should return migrations that were ran from ActiveRecord::Migrator.migrate' do
migrations = [mock('Migration 1')]
ActiveRecord::Migrator.stub(:migrate => migrations)
migrate.should == migrations
end
it 'should reset the column information' do
db_manager.should_receive(:reset_column_information)
migrate
end
context 'with StandardError from ActiveRecord::Migration.migrate' do
let(:error) do
StandardError.new(message)
end
let(:message) do
"Error during migration"
end
before(:each) do
ActiveRecord::Migrator.stub(:migrate).and_raise(error)
end
it 'should set Msf::DBManager#error' do
migrate
db_manager.error.should == error
end
it 'should log error message at error level' do
db_manager.should_receive(:elog) do |error_message|
error_message.should include(error.to_s)
end
migrate
end
it 'should log error backtrace at debug level' do
db_manager.should_receive(:dlog) do |debug_message|
debug_message.should include('Call stack')
end
migrate
end
end
context 'with verbose' do
def migrate
db_manager.migrate(verbose)
end
context 'false' do
let(:verbose) do
false
end
it 'should set ActiveRecord::Migration.verbose to false' do
ActiveRecord::Migration.should_receive(:verbose=).with(verbose)
migrate
end
end
context 'true' do
let(:verbose) do
true
end
it 'should set ActiveRecord::Migration.verbose to true' do
ActiveRecord::Migration.should_receive(:verbose=).with(verbose)
migrate
end
end
end
context 'without verbose' do
it 'should set ActiveRecord::Migration.verbose to false' do
ActiveRecord::Migration.should_receive(:verbose=).with(false)
db_manager.migrate
end
end
end
context '#migrated' do
it { should respond_to :migrated }
it { should respond_to :migrated= }
end
context '#reset_column_information' do
def reset_column_information
db_manager.send(:reset_column_information)
end
it 'should use ActiveRecord::Base.descendants to find both direct and indirect subclasses' do
ActiveRecord::Base.should_receive(:descendants).and_return([])
reset_column_information
end
it 'should reset column information on each descendant of ActiveRecord::Base' do
descendants = []
1.upto(2) do |i|
descendants << mock("Descendant #{i}")
end
ActiveRecord::Base.stub(:descendants => descendants)
descendants.each do |descendant|
descendant.should_receive(:reset_column_information)
end
reset_column_information
end
end
end