Skip to content

Commit ea41ec7

Browse files
committed
Fix tests leaving behind threads
1 parent 8205717 commit ea41ec7

File tree

6 files changed

+103
-56
lines changed

6 files changed

+103
-56
lines changed

lib/metasploit/framework/spec/threads/suite.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,6 @@ def self.configure!
100100

101101
# unmanaged thread, such as the main VM thread
102102
unless thread_uuid
103-
error_lines << "Thread has no uuid, thread name #{thread_name}"
104-
error_lines << "The thread backtrace was:\n#{thread.backtrace ? thread.backtrace.join("\n") : 'nil (no backtrace)'}\n"
105103
next
106104
end
107105

lib/msf/base/sessions/command_shell.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ def cmd_sessions(*args)
247247
session_id = args[0].to_i
248248
if session_id <= 0
249249
print_status 'Invalid session id'
250-
cmd_sessions_help
250+
return cmd_sessions_help
251251
end
252252

253253
if session_id == self.sid

lib/msf/ui/console/command_dispatcher/session.rb

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -182,20 +182,20 @@ def cmd_resource(*args)
182182
::Msf::Config.script_directory + ::File::SEPARATOR + 'resource' + ::File::SEPARATOR + 'meterpreter',
183183
::Msf::Config.user_script_directory + ::File::SEPARATOR + 'resource' + ::File::SEPARATOR + 'meterpreter'
184184
].each do |dir|
185-
res_path = dir + ::File::SEPARATOR + res
186-
if ::File.exist?(res_path)
187-
good_res = res_path
188-
break
189-
end
190-
end
185+
res_path = dir + ::File::SEPARATOR + res
186+
if ::File.exist?(res_path)
187+
good_res = res_path
188+
break
189+
end
190+
end
191191
# let's check to see if it's in the scripts/resource dir (like when tab completed)
192192
end
193-
if good_res
194-
client.console.load_resource(good_res)
195-
else
193+
unless good_res
196194
print_error("#{res} is not a valid resource file")
197195
next
198196
end
197+
198+
client.console.load_resource(good_res)
199199
end
200200
end
201201

@@ -220,7 +220,8 @@ def cmd_resource_tabs(str, words)
220220
::File.file?(path) and ::File.readable?(path)
221221
end
222222
end
223-
rescue Exception
223+
rescue StandardError => e
224+
elog('Problem tab completing resource file names in the scripts/resource directories', error: e)
224225
end
225226
else
226227
tabs += tab_complete_filenames(str, words)

spec/lib/msf/base/sessions/command_shell_spec.rb

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@
55
RSpec.describe Msf::Sessions::CommandShell do
66
let(:type) { 'shell' }
77

8-
it 'should have the correct type' do
9-
expect(described_class.type).to eq(type)
8+
describe '.type' do
9+
it 'should have the correct type' do
10+
expect(described_class.type).to eq(type)
11+
end
1012
end
1113

12-
it 'should be able to cleanup files' do
13-
expect(described_class.can_cleanup_files).to eq(true)
14+
describe '.can_cleanup_files' do
15+
it 'should be able to cleanup files' do
16+
expect(described_class.can_cleanup_files).to eq(true)
17+
end
1418
end
1519

1620
context 'when we have a command shell session' do
@@ -23,37 +27,48 @@
2327
end
2428
let(:description) { 'Command shell' }
2529

26-
it 'should have the correct type' do
27-
expect(subject.type).to eq(type)
30+
describe '#type' do
31+
it 'should have the correct type' do
32+
expect(subject.type).to eq(type)
33+
end
2834
end
29-
it 'should have the correct description' do
30-
expect(subject.desc).to eq(description)
35+
36+
describe '#desc' do
37+
it 'should have the correct description' do
38+
expect(subject.desc).to eq(description)
39+
end
3140
end
3241

33-
it 'should not support aborting the process running in the session' do
34-
expect(subject.abort_foreground_supported).to be(true)
42+
describe '#abort_foreground_supported' do
43+
it 'should not support aborting the process running in the session' do
44+
expect(subject.abort_foreground_supported).to be(true)
45+
end
3546
end
3647

37-
it 'should initialise the shell by default' do
38-
expect(subject.shell_init).to be(true)
48+
describe '#shell_init' do
49+
it 'should initialise the shell by default' do
50+
expect(subject.shell_init).to be(true)
51+
end
3952
end
4053

4154
describe 'Builtin commands' do
42-
%i[help background sessions resource shell download upload source irb pry].each do |command|
43-
next if command == :help
55+
%i[background sessions resource shell download upload source irb pry].each do |command|
56+
before(:each) do
57+
allow(subject).to receive("cmd_#{command}_help")
58+
end
4459

4560
describe "#cmd_#{command}" do
4661
context 'when called with the `-h` argument' do
4762
it 'should call the corresponding help function' do
48-
expect(subject).to receive("cmd_#{command}_help")
4963
subject.send("cmd_#{command}", '-h')
64+
expect(subject).to have_received("cmd_#{command}_help")
5065
end
5166
end
5267

5368
context 'when called with the `--help` argument' do
5469
it 'should call the corresponding help function' do
55-
expect(subject).to receive("cmd_#{command}_help")
5670
subject.send("cmd_#{command}", '--help')
71+
expect(subject).to have_received("cmd_#{command}_help")
5772
end
5873
end
5974
end
@@ -62,30 +77,37 @@
6277

6378
describe '#run_builtin_cmd' do
6479
%i[help background sessions resource shell download upload source irb pry].each do |command|
80+
before(:each) do
81+
allow(subject).to receive("cmd_#{command}")
82+
end
6583
context "when called with `#{command}`" do
6684
it "should call cmd_#{command}" do
67-
expect(subject).to receive("cmd_#{command}")
6885
subject.run_builtin_cmd(command.to_s, nil)
86+
expect(subject).to have_received("cmd_#{command}")
6987
end
7088
end
7189
end
7290
end
7391

7492
describe '#run_single' do
93+
before(:each) do
94+
allow(subject).to receive(:run_builtin_cmd)
95+
allow(subject).to receive(:shell_write)
96+
end
7597
%i[help background sessions resource shell download upload source irb pry].each do |command|
7698
context "when called with builtin command `#{command}`" do
7799
it 'should call the builtin function' do
78-
expect(subject).to receive(:run_builtin_cmd)
79100
subject.run_single(command.to_s)
101+
expect(subject).to have_received(:run_builtin_cmd)
80102
end
81103
end
82104
end
83105

84106
context 'when called with a non-builtin command' do
85107
let(:cmd) { 'some_command' }
86108
it 'should write the command to the shell' do
87-
expect(subject).to receive(:shell_write).with("#{cmd}\n")
88109
subject.run_single(cmd)
110+
expect(subject).to have_received(:shell_write).with("#{cmd}\n")
89111
end
90112
end
91113
end
@@ -94,13 +116,17 @@
94116
let(:initial_auto_run_script) { 'initial_auto_run_script' }
95117
let(:auto_run_script) { 'auto_run_script' }
96118

119+
before(:each) do
120+
allow(subject).to receive(:execute_script)
121+
end
122+
97123
context 'The datastore is empty' do
98124
let(:datastore) do
99125
Msf::DataStore.new
100126
end
101127
it 'should not execute any script' do
102-
is_expected.not_to receive(:execute_script)
103128
subject.process_autoruns(datastore)
129+
is_expected.not_to have_received(:execute_script)
104130
end
105131
end
106132

@@ -110,9 +136,10 @@
110136
datastore['InitialAutoRunScript'] = initial_auto_run_script
111137
datastore
112138
end
139+
113140
it 'should execute the script' do
114-
is_expected.to receive(:execute_script).with(initial_auto_run_script)
115141
subject.process_autoruns(datastore)
142+
is_expected.to have_received(:execute_script).with(initial_auto_run_script)
116143
end
117144
end
118145

@@ -123,8 +150,8 @@
123150
datastore
124151
end
125152
it 'should execute the script' do
126-
is_expected.to receive(:execute_script).with(auto_run_script)
127153
subject.process_autoruns(datastore)
154+
is_expected.to have_received(:execute_script).with(auto_run_script)
128155
end
129156
end
130157

@@ -136,9 +163,9 @@
136163
datastore
137164
end
138165
it 'should execute initial script before the auto run script' do
139-
is_expected.to receive(:execute_script).ordered.with(initial_auto_run_script)
140-
is_expected.to receive(:execute_script).ordered.with(auto_run_script)
141166
subject.process_autoruns(datastore)
167+
is_expected.to have_received(:execute_script).ordered.with(initial_auto_run_script)
168+
is_expected.to have_received(:execute_script).ordered.with(auto_run_script)
142169
end
143170
end
144171
end

spec/lib/rex/post/meterpreter/ui/console/command_dispatcher/core_spec.rb

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,22 @@
22

33
require 'spec_helper'
44
require 'rex/post/meterpreter/ui/console/command_dispatcher/core'
5-
require 'lib/msf/ui/console/command_dispatcher/session_spec'
65

76
RSpec.describe Rex::Post::Meterpreter::Ui::Console::CommandDispatcher::Core do
8-
let(:client) do
9-
client = Msf::Sessions::Meterpreter.new(nil)
10-
client.interacting = true
11-
client
12-
end
13-
let(:shell) do
7+
let(:client) { instance_double(Msf::Sessions::Meterpreter) }
8+
let(:console) do
149
console = Rex::Post::Meterpreter::Ui::Console.new(client)
1510
console.disable_output = true
1611
console
1712
end
1813

19-
subject(:command_dispatcher) { described_class.new(shell) }
14+
before(:each) do
15+
allow(client).to receive(:console).and_return(console)
16+
allow(client).to receive(:name).and_return('test client name')
17+
allow(client).to receive(:sid).and_return('test client sid')
18+
end
19+
20+
subject(:command_dispatcher) { described_class.new(client.console) }
2021

2122
it_behaves_like 'session command dispatcher'
2223
end

spec/lib/msf/ui/console/command_dispatcher/session_spec.rb renamed to spec/support/shared/examples/msf/ui/console/command_dispatcher/session_spec.rb

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
require 'spec_helper'
2+
13
RSpec.shared_examples_for 'session command dispatcher' do
24
include_context 'Msf::Simple::Framework'
3-
# include_context 'Msf::Framework#threads cleaner', verify_cleanup_required: false
45

56
describe '#client' do
67
subject { command_dispatcher.client }
@@ -9,9 +10,13 @@
910

1011
describe 'Core commands' do
1112
describe '#cmd_background' do
13+
before(:each) do
14+
allow(client).to receive(:interacting=)
15+
end
16+
1217
it 'backgrounds the session' do
1318
subject.cmd_background
14-
expect(client.interacting).to be(false)
19+
expect(client).to have_received(:interacting=).with(false)
1520
end
1621

1722
it 'is aliased to #cmd_bg' do
@@ -20,9 +25,13 @@
2025
end
2126

2227
describe '#cmd_exit' do
28+
before(:each) do
29+
allow(client).to receive(:exit)
30+
end
31+
2332
it 'shuts down the session' do
24-
expect(client).to receive(:exit)
2533
subject.cmd_exit
34+
expect(client).to have_received(:exit)
2635
end
2736

2837
it 'is aliased to #cmd_quit' do
@@ -36,55 +45,66 @@
3645
allow(client).to receive(:framework).and_return(framework)
3746
allow(framework).to receive(:history_manager).and_return(history_manager)
3847
allow(history_manager).to receive(:with_context).and_yield
48+
allow(Rex::Ui::Text::IrbShell).to receive(:new).with(client).and_return(irb_shell)
49+
allow(irb_shell).to receive(:run)
3950
end
4051
let(:irb_shell) { instance_double(Rex::Ui::Text::IrbShell) }
4152
it 'runs an irb shell instance' do
42-
expect(Rex::Ui::Text::IrbShell).to receive(:new).with(client).and_return(irb_shell)
43-
expect(irb_shell).to receive(:run)
4453
subject.cmd_irb
54+
expect(Rex::Ui::Text::IrbShell).to have_received(:new).with(client)
55+
expect(irb_shell).to have_received(:run)
4556
end
4657
end
4758

4859
describe '#cmd_sessions' do
4960
context 'when switching to a new session' do
61+
before(:each) do
62+
allow(client).to receive(:interacting=)
63+
allow(client).to receive(:next_session=)
64+
end
65+
5066
let(:new_session_id) { 2 }
5167

5268
it 'backgrounds the session and switches to the new session' do
5369
subject.cmd_sessions(new_session_id)
54-
expect(client.interacting).to be(false)
55-
expect(client.next_session).to eq(new_session_id)
70+
expect(client).to have_received(:interacting=).with(false)
71+
expect(client).to have_received(:next_session=).with(new_session_id)
5672
end
5773
end
5874
end
5975

6076
describe '#cmd_resource' do
61-
context 'there is a valid resource script' do
77+
context 'when there is a valid resource script' do
6278
let(:valid_resource_path) { 'valid/resource/path' }
6379
before(:each) do
6480
allow(File).to receive(:exist?).and_return(valid_resource_path)
81+
allow(client.console).to receive(:load_resource)
6582
end
6683
it 'executes the resource script' do
67-
expect(client.console).to receive(:load_resource).with(valid_resource_path)
6884
subject.cmd_resource(valid_resource_path)
85+
expect(client.console).to have_received(:load_resource).with(valid_resource_path)
6986
end
7087
end
7188
end
7289

7390
%i[help background sessions resource irb pry exit].each do |command|
7491
describe "#cmd_#{command}" do
92+
before(:each) do
93+
allow(subject).to receive("cmd_#{command}_help")
94+
end
7595
next if %i[help exit].include?(command) # These commands don't require`-h/--help`
7696

7797
context 'when called with the `-h` argument' do
7898
it 'should call the corresponding help function' do
79-
expect(subject).to receive("cmd_#{command}_help")
8099
subject.send("cmd_#{command}", '-h')
100+
expect(subject).to have_received("cmd_#{command}_help")
81101
end
82102
end
83103

84104
context 'when called with the `--help` argument' do
85105
it 'should call the corresponding help function' do
86-
expect(subject).to receive("cmd_#{command}_help")
87106
subject.send("cmd_#{command}", '--help')
107+
expect(subject).to have_received("cmd_#{command}_help")
88108
end
89109
end
90110
end

0 commit comments

Comments
 (0)