Skip to content

Commit b7ebc29

Browse files
authored
Merge pull request #3462 from kaitozaw/test/rspec-isolation
Fixes #3464
2 parents eb4fa92 + d3724b8 commit b7ebc29

8 files changed

Lines changed: 72 additions & 1 deletion

File tree

spec/beef/core/main/autorun_engine/autorun_engine_spec.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
RSpec.describe 'AutoRunEngine Test', run_on_browserstack: true do
1414
before(:all) do
15+
@__ar_config_snapshot = SpecActiveRecordConnection.snapshot
1516
@config = BeEF::Core::Configuration.instance
1617

1718
# Grab DB file and regenerate if requested
@@ -110,6 +111,7 @@
110111
after(:all) do
111112
server_teardown(@driver, @pid, @pids)
112113
disconnect_all_active_record!
114+
SpecActiveRecordConnection.restore!(@__ar_config_snapshot)
113115
end
114116

115117
it 'AutoRunEngine is working' do

spec/beef/core/main/handlers/browser_details_handler_spec.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
RSpec.describe 'Browser Details Handler', run_on_browserstack: true do
1414
before(:all) do
15-
15+
@__ar_config_snapshot = SpecActiveRecordConnection.snapshot
1616
@config = BeEF::Core::Configuration.instance
1717
db_file = @config.get('beef.database.file')
1818
print_info 'Resetting the database for BeEF.'
@@ -106,6 +106,7 @@
106106
after(:all) do
107107
server_teardown(@driver, @pid, @pids)
108108
disconnect_all_active_record!
109+
SpecActiveRecordConnection.restore!(@__ar_config_snapshot)
109110
end
110111

111112
it 'can successfully hook a browser' do

spec/beef/core/main/network_stack/handlers/dynamic_reconstruction_spec.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
RSpec.describe 'BeEF Dynamic Reconsturction' do
22

33
before(:all) do
4+
@__ar_config_snapshot = SpecActiveRecordConnection.snapshot
45
@port = 2001
56
config = {}
67
config[:BindAddress] = '127.0.0.1'
@@ -25,6 +26,7 @@
2526

2627
after(:all) do
2728
Process.kill("INT",@pid)
29+
SpecActiveRecordConnection.restore!(@__ar_config_snapshot)
2830
end
2931

3032
it 'delete' do

spec/beef/core/main/network_stack/handlers/redirector_spec.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
RSpec.describe 'BeEF Redirector' do
22

33
before(:all) do
4+
@__ar_config_snapshot = SpecActiveRecordConnection.snapshot
45
@port = 2002
56
config = {}
67
config[:BindAddress] = '127.0.0.1'
@@ -26,6 +27,7 @@
2627

2728
after(:all) do
2829
Process.kill("INT",@pid)
30+
SpecActiveRecordConnection.restore!(@__ar_config_snapshot)
2931
end
3032

3133
it 'redirects' do

spec/beef/extensions/requester_spec.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
xit 'requester works' do
2626
begin
27+
ar_snapshot = SpecActiveRecordConnection.snapshot
2728
# Start beef server
2829
@config = BeEF::Core::Configuration.instance
2930
@config.set('beef.credentials.user', 'beef')
@@ -77,6 +78,7 @@
7778
BeEF::Core::Models::Http.where(hooked_browser_id: hb_session).delete_all if defined? hb_session
7879
Process.kill('KILL', @pid) if defined? @pid
7980
Process.kill('KILL', @pids) if defined? @pids
81+
SpecActiveRecordConnection.restore!(ar_snapshot)
8082
end
8183
end
8284
end

spec/beef/extensions/websocket_hooked_browser_spec.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
RSpec.describe 'Browser hooking with Websockets', run_on_browserstack: true do
1515
before(:all) do
16+
@__ar_config_snapshot = SpecActiveRecordConnection.snapshot
1617
@config = BeEF::Core::Configuration.instance
1718
# Grab DB file and regenerate if requested
1819
print_info 'Loading database'
@@ -104,6 +105,7 @@
104105
after(:all) do
105106
server_teardown(@driver, @pid, @pids)
106107
disconnect_all_active_record!
108+
SpecActiveRecordConnection.restore!(@__ar_config_snapshot)
107109
end
108110

109111
it 'confirms a websocket server has been started' do

spec/beef/modules/debug/test_beef_debugs_spec.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
RSpec.describe 'BeEF Debug Command Modules:', run_on_browserstack: true do
1414
before(:all) do
15+
@__ar_config_snapshot = SpecActiveRecordConnection.snapshot
1516
# Grab config and set creds in variables for ease of access
1617
@config = BeEF::Core::Configuration.instance
1718
@pids = [] # ensure defined for teardown consistency
@@ -128,6 +129,7 @@
128129
after(:all) do
129130
server_teardown(@driver, @pid, @pids)
130131
disconnect_all_active_record!
132+
SpecActiveRecordConnection.restore!(@__ar_config_snapshot)
131133
end
132134

133135
it 'The Test_beef.debug() command module successfully executes' do

spec/spec_helper.rb

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,8 @@ def start_beef_server
271271
# Generate a token for the server to respond with
272272
BeEF::Core::Crypto::api_token
273273

274+
disconnect_all_active_record!
275+
274276
# Initiate server start-up
275277
BeEF::API::Registrar.instance.fire(BeEF::API::Server, 'pre_http_start', http_hook_server)
276278
pid = fork do
@@ -322,4 +324,60 @@ def stop_beef_server(pid)
322324
pid = nil
323325
end
324326

327+
end
328+
329+
# -------------------------------------------------------------------
330+
# ActiveRecord connection snapshot/restore helpers (test isolation)
331+
# Some specs disconnect ActiveRecord (fork safety), destroying the SQLite in-memory DB.
332+
# These helpers restore it for later specs.
333+
# -------------------------------------------------------------------
334+
module SpecActiveRecordConnection
335+
module_function
336+
337+
def snapshot
338+
# Capture the current AR connection configuration hash if possible.
339+
if ActiveRecord::Base.respond_to?(:connection_db_config) && ActiveRecord::Base.connection_db_config
340+
ActiveRecord::Base.connection_db_config.configuration_hash
341+
else
342+
ActiveRecord::Base.connection_config
343+
end
344+
rescue StandardError
345+
nil
346+
end
347+
348+
def restore!(config_hash)
349+
# Ensure we don't leave AR disconnected for subsequent specs.
350+
begin
351+
handler = ActiveRecord::Base.connection_handler
352+
if handler.respond_to?(:connection_pool_list)
353+
handler.connection_pool_list.each { |pool| pool.disconnect! }
354+
elsif handler.respond_to?(:connection_pools)
355+
handler.connection_pools.each_value { |pool| pool.disconnect! }
356+
else
357+
ActiveRecord::Base.connection_pool.disconnect!
358+
end
359+
rescue StandardError
360+
# ignore
361+
end
362+
363+
if config_hash
364+
OTR::ActiveRecord.configure_from_hash!(config_hash)
365+
else
366+
# Fallback to suite default
367+
OTR::ActiveRecord.configure_from_hash!(adapter: 'sqlite3', database: ':memory:')
368+
end
369+
370+
if Gem.loaded_specs['otr-activerecord'].version > Gem::Version.create('1.4.2')
371+
OTR::ActiveRecord.establish_connection!
372+
end
373+
ActiveRecord::Schema.verbose = false
374+
375+
# Run migrations if the restored DB is empty/outdated
376+
ActiveRecord::Migration.verbose = false
377+
ActiveRecord::Migrator.migrations_paths = [File.join('core', 'main', 'ar-migrations')]
378+
context = ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths)
379+
if context.needs_migration?
380+
ActiveRecord::Migrator.new(:up, context.migrations, context.schema_migration, context.internal_metadata).migrate
381+
end
382+
end
325383
end

0 commit comments

Comments
 (0)