beaker 4.26.0 → 4.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,6 +5,7 @@ module Unix::Pkg
5
5
  # unix-specific package management setup
6
6
  def pkg_initialize
7
7
  @apt_needs_update = true
8
+ @pacman_needs_update = true
8
9
  end
9
10
 
10
11
  def check_for_command(name)
@@ -71,6 +72,17 @@ module Unix::Pkg
71
72
  end
72
73
  end
73
74
 
75
+ # Arch Linux is a rolling release distribution. We need to ensure that it is up2date
76
+ # Except for the kernel. An upgrade will purge the modules for the currently running kernel
77
+ def update_pacman_if_needed
78
+ if self['platform'] =~ /archlinux/
79
+ if @pacman_needs_update
80
+ execute("pacman --sync --noconfirm --noprogressbar --refresh --sysupgrade --ignore linux --ignore linux-docs --ignore linux-headers")
81
+ @pacman_needs_update = false
82
+ end
83
+ end
84
+ end
85
+
74
86
  def install_package(name, cmdline_args = '', version = nil, opts = {})
75
87
  case self['platform']
76
88
  when /sles-/
@@ -138,6 +150,7 @@ module Unix::Pkg
138
150
  retry
139
151
  end
140
152
  when /archlinux/
153
+ update_pacman_if_needed
141
154
  execute("pacman -S --noconfirm #{cmdline_args} #{name}", opts)
142
155
  else
143
156
  raise "Package #{name} cannot be installed on #{self}"
@@ -6,11 +6,12 @@ module Beaker
6
6
  PLATFORMS = /^(alpine|huaweios|cisco_nexus|cisco_ios_xr|(free|open)bsd|osx|centos|fedora|debian|oracle|redhat|redhatfips|scientific|sles|ubuntu|windows|solaris|aix|archlinux|el|eos|cumulus|f5|netscaler)\-.+\-.+$/
7
7
  # Platform version numbers vs. codenames conversion hash
8
8
  PLATFORM_VERSION_CODES =
9
- { :debian => { "buster" => "10",
10
- "stretch" => "9",
11
- "jessie" => "8",
12
- "wheezy" => "7",
13
- "squeeze" => "6",
9
+ { :debian => { "bullseye" => "11",
10
+ "buster" => "10",
11
+ "stretch" => "9",
12
+ "jessie" => "8",
13
+ "wheezy" => "7",
14
+ "squeeze" => "6",
14
15
  },
15
16
  :ubuntu => { "focal" => "2004",
16
17
  "eoan" => "1910",
@@ -1,5 +1,5 @@
1
1
  module Beaker
2
2
  module Version
3
- STRING = '4.26.0'
3
+ STRING = '4.29.0'
4
4
  end
5
5
  end
@@ -89,6 +89,7 @@ describe ClassMixedWithDSLHelpers do
89
89
  describe "#fetch_http_dir" do
90
90
  let( :logger) { double("Beaker::Logger", :notify => nil , :debug => nil ) }
91
91
  let( :result) { double(:each_line => []) }
92
+ let( :status) { double('Process::Status', success?: true) }
92
93
 
93
94
  before do
94
95
  fetch_allows
@@ -97,8 +98,7 @@ describe ClassMixedWithDSLHelpers do
97
98
  describe "given valid arguments" do
98
99
 
99
100
  it "returns basename of first argument concatenated to second." do
100
- expect(subject).to receive(:`).with(/^wget.*/).ordered { result }
101
- expect($?).to receive(:to_i).and_return(0)
101
+ expect(Open3).to receive(:capture2e).with(/^wget.*/).ordered { result }.and_return(['', status])
102
102
  result = subject.fetch_http_dir "#{url}/beep", destdir
103
103
  expect(result).to eq("#{destdir}/beep")
104
104
  end
@@ -29,8 +29,8 @@ module Beaker
29
29
  it "deletes" do
30
30
  path = '/path/to/delete'
31
31
  corrected_path = '\\path\\to\\delete'
32
- expect( instance ).to receive(:execute).with("del /s /q #{corrected_path}").and_return(0)
33
- expect( instance.rm_rf(path) ).to be === 0
32
+ expect(instance).to receive(:execute).with(%(del /s /q "#{corrected_path}")).and_return(0)
33
+ expect(instance.rm_rf(path)).to eq(0)
34
34
  end
35
35
  end
36
36
 
@@ -39,10 +39,9 @@ module Beaker
39
39
  let(:destination) { '/destination/path/of/content' }
40
40
 
41
41
  it 'rm first' do
42
- expect( instance ).to receive(:execute).with("del /s /q #{destination.gsub(/\//, '\\')}").and_return(0)
43
- expect( instance ).to receive(:execute).with("move /y #{origin.gsub(/\//, '\\')} #{destination.gsub(/\//, '\\')}").and_return(0)
44
- expect( instance.mv(origin, destination) ).to be === 0
45
-
42
+ expect(instance).to receive(:execute).with("del /s /q \"\\destination\\path\\of\\content\"").and_return(0)
43
+ expect(instance).to receive(:execute).with("move /y #{origin.gsub(/\//, '\\')} #{destination.gsub(/\//, '\\')}").and_return(0)
44
+ expect(instance.mv(origin, destination)).to eq(0)
46
45
  end
47
46
 
48
47
  it 'does not rm' do
@@ -169,6 +169,66 @@ module Beaker
169
169
  end
170
170
 
171
171
  describe '#reboot' do
172
+ year = Time.now.strftime('%Y')
173
+
174
+ check_cmd_output = {
175
+ :centos6 => {
176
+ :who => {
177
+ :initial => " system boot #{year}-05-13 03:51",
178
+ :success => " system boot #{year}-05-13 03:52",
179
+ },
180
+ :last => {
181
+ :initial => <<~LAST_F,
182
+ reboot system boot 2.6.32-754.29.1. Tue May 5 17:34:52 #{year} - Tue May 5 17:52:48 #{year} (00:17)
183
+ reboot system boot 2.6.32-754.29.1. Mon May 4 18:45:43 #{year} - Mon May 5 05:35:44 #{year} (4+01:50)
184
+ LAST_F
185
+ :success => <<~LAST_F,
186
+ reboot system boot 2.6.32-754.29.1. Tue May 5 17:52:48 #{year} - Tue May 5 17:52:49 #{year} (00:17)
187
+ reboot system boot 2.6.32-754.29.1. Mon May 4 18:45:43 #{year} - Mon May 5 05:35:44 #{year} (4+01:50)
188
+ LAST_F
189
+ },
190
+ },
191
+ :centos7 => {
192
+ :who => {
193
+ :initial => " system boot #{year}-05-13 03:51",
194
+ :success => " system boot #{year}-05-13 03:52",
195
+ },
196
+ :last => {
197
+ :initial => <<~LAST_F,
198
+ reboot system boot 3.10.0-1127.el7. Tue May 5 17:34:52 #{year} - Tue May 5 17:52:48 #{year} (00:17)
199
+ reboot system boot 3.10.0-1127.el7. Mon May 4 18:45:43 #{year} - Mon May 5 05:35:44 #{year} (4+01:50)
200
+ LAST_F
201
+ :success => <<~LAST_F,
202
+ reboot system boot 3.10.0-1127.el7. Tue May 5 17:52:48 #{year} - Tue May 5 17:52:49 #{year} (00:17)
203
+ reboot system boot 3.10.0-1127.el7. Mon May 4 18:45:43 #{year} - Mon May 5 05:35:44 #{year} (4+01:50)
204
+ LAST_F
205
+ },
206
+ },
207
+ :centos8 => {
208
+ :who => {
209
+ :initial => " system boot #{year}-05-13 03:51",
210
+ :success => " system boot #{year}-05-13 03:52",
211
+ },
212
+ :last => {
213
+ :initial => <<~LAST_F,
214
+ reboot system boot 4.18.0-147.8.1.e Tue May 5 17:34:52 #{year} still running
215
+ reboot system boot 4.18.0-147.8.1.e Mon May 4 17:41:27 #{year} - Tue May 5 17:00:00 #{year} (5+00:11)
216
+ LAST_F
217
+ :success => <<~LAST_F,
218
+ reboot system boot 4.18.0-147.8.1.e Tue May 5 17:34:53 #{year} still running
219
+ reboot system boot 4.18.0-147.8.1.e Mon May 4 17:41:27 #{year} - Tue May 5 17:00:00 #{year} (5+00:11)
220
+ LAST_F
221
+ },
222
+ },
223
+ :freebsd => {
224
+ # last -F doesn't work on freebsd so no output will be returned
225
+ :who => {
226
+ :initial => ' system boot May 13 03:51',
227
+ :success => ' system boot May 13 03:52',
228
+ }
229
+ },
230
+ }
231
+
172
232
  # no-op response
173
233
  let (:response) { double( 'response' ) }
174
234
  let (:boot_time_initial_response) { double( 'response' ) }
@@ -179,7 +239,7 @@ module Beaker
179
239
  before :each do
180
240
  # stubs enough to survive the first boot_time call & output parsing
181
241
  # note: just stubs input-chain between calls, parsing methods still run
182
- allow(Beaker::Command).to receive(:new).with('who -b').and_return(:boot_time_command_stub)
242
+ allow(Beaker::Command).to receive(:new).with('last -F reboot || who -b').and_return(:boot_time_command_stub)
183
243
 
184
244
  allow(boot_time_initial_response).to receive(:stdout).and_return(boot_time_initial_stdout)
185
245
  allow(boot_time_success_response).to receive(:stdout).and_return(boot_time_success_stdout)
@@ -190,116 +250,128 @@ module Beaker
190
250
  end
191
251
 
192
252
  context 'new boot time greater than old boot time' do
193
- let (:boot_time_initial_stdout) { ' system boot 2020-05-13 03:51' }
194
- let (:boot_time_success_stdout) { ' system boot 2020-05-13 03:52' }
195
-
196
- it 'passes with defaults' do
197
- expect(instance).to receive(:sleep).with(sleep_time)
198
- # bypass shutdown command itself
199
- expect(instance).to receive( :exec ).with(:shutdown_command_stub, anything).and_return(response)
200
- # allow the second boot_time and the hash arguments in exec
201
- expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_initial_response).once
202
- expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_success_response).once
203
-
204
- expect(instance.reboot).to be(nil)
205
- end
253
+ check_cmd_output.each do |check_os, cmd_opts|
254
+ cmd_opts.each do |cmd_name, cmd_outputs|
255
+ context "on '#{check_os}' with the '#{cmd_name}' command" do
256
+ let (:boot_time_initial_stdout) { cmd_outputs[:initial] }
257
+ let (:boot_time_success_stdout) { cmd_outputs[:success] }
258
+
259
+ it 'passes with defaults' do
260
+ expect(instance).to receive(:sleep).with(sleep_time)
261
+ # bypass shutdown command itself
262
+ expect(instance).to receive( :exec ).with(:shutdown_command_stub, anything).and_return(response)
263
+ expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_initial_response).once
264
+ # allow the second boot_time and the hash arguments in exec
265
+ expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_success_response).once
206
266
 
207
- it 'passes with wait_time_parameter' do
208
- expect(instance).to receive(:sleep).with(10)
209
- # bypass shutdown command itself
210
- expect(instance).to receive( :exec ).with(:shutdown_command_stub, anything).and_return(response).once
211
- expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_initial_response).once
212
- # allow the second boot_time and the hash arguments in exec
213
- expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_success_response).once
267
+ expect(instance.reboot).to be(nil)
268
+ end
214
269
 
215
- expect(instance.reboot(10)).to be(nil)
216
- end
270
+ it 'passes with wait_time_parameter' do
271
+ expect(instance).to receive(:sleep).with(10)
272
+ # bypass shutdown command itself
273
+ expect(instance).to receive( :exec ).with(:shutdown_command_stub, anything).and_return(response).once
274
+ expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_initial_response).once
275
+ # allow the second boot_time and the hash arguments in exec
276
+ expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_success_response).once
217
277
 
218
- it 'passes with max_connection_tries parameter' do
219
- expect(instance).to receive(:sleep).with(sleep_time)
220
- # bypass shutdown command itself
221
- expect(instance).to receive( :exec ).with(:shutdown_command_stub, anything).and_return(response).once
222
- expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_initial_response).once
223
- # allow the second boot_time and the hash arguments in exec
224
- expect(instance).to receive( :exec ).with(:boot_time_command_stub, hash_including(:max_connection_tries => 20)).and_return(boot_time_success_response).once
278
+ expect(instance.reboot(10)).to be(nil)
279
+ end
225
280
 
226
- expect(instance.reboot(sleep_time, 20)).to be(nil)
227
- end
281
+ it 'passes with max_connection_tries parameter' do
282
+ expect(instance).to receive(:sleep).with(sleep_time)
283
+ # bypass shutdown command itself
284
+ expect(instance).to receive( :exec ).with(:shutdown_command_stub, anything).and_return(response).once
285
+ expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_initial_response).once
286
+ # allow the second boot_time and the hash arguments in exec
287
+ expect(instance).to receive( :exec ).with(:boot_time_command_stub, hash_including(:max_connection_tries => 20)).and_return(boot_time_success_response).once
228
288
 
229
- context 'command errors' do
230
- before :each do
231
- allow(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_initial_response).once
232
- end
289
+ expect(instance.reboot(sleep_time, 20)).to be(nil)
290
+ end
233
291
 
234
- it 'raises a reboot failure when command fails' do
235
- expect(instance).not_to receive(:sleep)
236
- expect(instance).to receive(:exec).with(:shutdown_command_stub, anything).and_raise(Host::CommandFailure).once
292
+ context 'command errors' do
293
+ before :each do
294
+ allow(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_initial_response).at_least(:once)
295
+ end
237
296
 
238
- expect{ instance.reboot }.to raise_error(Beaker::Host::RebootFailure, /Command failed when attempting to reboot: .*/)
239
- end
297
+ it 'raises a reboot failure when command fails' do
298
+ expect(instance).to receive(:sleep).at_least(:once)
299
+ expect(instance).to receive(:exec).with(:shutdown_command_stub, anything).and_raise(Host::CommandFailure).at_least(:once)
240
300
 
241
- it 'raises a reboot failure when we receive an unexpected error' do
242
- expect(instance).not_to receive(:sleep)
243
- expect(instance).to receive(:exec).with(:shutdown_command_stub, anything).and_raise(Net::SSH::HostKeyError).once
301
+ expect{ instance.reboot }.to raise_error(Beaker::Host::CommandFailure)
302
+ end
244
303
 
245
- expect { instance.reboot }.to raise_error(Beaker::Host::RebootFailure, /Unexpected exception in reboot: .*/)
246
- end
304
+ it 'raises a reboot failure when we receive an unexpected error' do
305
+ expect(instance).to receive(:sleep).at_least(:once)
306
+ expect(instance).to receive(:exec).with(:shutdown_command_stub, anything).and_raise(Net::SSH::HostKeyError).at_least(:once)
247
307
 
248
- context 'incorrect time string' do
249
- context 'original time' do
250
- let (:boot_time_initial_stdout) { 'boot bad' }
308
+ expect { instance.reboot }.to raise_error(Net::SSH::HostKeyError)
309
+ end
251
310
 
252
- it 'raises a reboot failure' do
253
- expect(instance).not_to receive(:sleep)
311
+ context 'incorrect time string' do
312
+ context 'original time' do
313
+ let (:boot_time_initial_stdout) { 'boot bad' }
254
314
 
255
- expect { instance.reboot }.to raise_error(Beaker::Host::RebootFailure, /Unable to parse time: .*/)
256
- end
257
- end
315
+ it 'raises a reboot failure' do
316
+ # Handle the 'retry'
317
+ allow(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_initial_response).at_least(:once)
258
318
 
259
- context 'current time' do
260
- let (:boot_time_success_stdout) { 'boot bad' }
319
+ expect(instance).not_to receive(:sleep)
261
320
 
262
- it 'raises a reboot failure' do
263
- expect(instance).to receive(:exec).with(:shutdown_command_stub, anything).and_return(response).once
264
- expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_initial_response).once
265
- # allow the second boot_time and the hash arguments in exec, repeated 10 times by default
266
- expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_success_response).once
321
+ expect { instance.reboot }.to raise_error(Beaker::Host::RebootWarning, /Found no valid times in .*/)
322
+ end
323
+ end
324
+
325
+ context 'current time' do
326
+ let (:boot_time_success_stdout) { 'boot bad' }
327
+
328
+ it 'raises a reboot failure' do
329
+ expect(instance).to receive(:exec).with(:shutdown_command_stub, anything).and_return(response).once
330
+ expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_initial_response).once
331
+ # allow the second boot_time and the hash arguments in exec, repeated 10 times by default
332
+ expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_success_response).at_least(:once)
267
333
 
268
- expect { instance.reboot }.to raise_error(Beaker::Host::RebootFailure, /Unable to parse time: .*/)
334
+ expect { instance.reboot(10,9,1) }.to raise_error(Beaker::Host::RebootWarning, /Found no valid times in .*/)
335
+ end
336
+ end
337
+ end
269
338
  end
270
339
  end
271
340
  end
272
341
  end
273
342
  end
274
343
 
275
- context 'new boot time less than old boot time' do
276
- let (:boot_time_initial_stdout) { ' system boot 2020-05-13 03:51' }
277
- let (:boot_time_success_stdout) { ' system boot 2020-05-13 03:50' }
344
+ context 'system did not reboot' do
345
+ check_cmd_output.each do |check_os, cmd_opts|
346
+ cmd_opts.each do |cmd_name, cmd_outputs|
347
+ context "on '#{check_os}' with the '#{cmd_name}' command" do
348
+ let (:boot_time_initial_stdout) { cmd_outputs[:initial] }
349
+ let (:boot_time_success_stdout) { cmd_outputs[:initial] }
278
350
 
279
- it 'raises RebootFailure' do
280
- expect(instance).to receive(:sleep).with(sleep_time)
281
- # bypass shutdown command itself
282
- expect(instance).to receive( :exec ).with(:shutdown_command_stub, anything).and_return(response).once
351
+ it 'raises RebootFailure' do
352
+ expect(instance).to receive(:sleep).with(sleep_time)
353
+ # bypass shutdown command itself
354
+ expect(instance).to receive( :exec ).with(:shutdown_command_stub, anything).and_return(response).once
283
355
 
284
- expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_initial_response).once
285
- # allow the second boot_time and the hash arguments in exec, repeated 18 times by default in order to replicate the previous behavior of the ping based Host.down?
286
- expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_success_response).exactly(18).times
356
+ expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_initial_response).once
357
+ expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_success_response).once
287
358
 
288
- expect { instance.reboot }.to raise_error(Beaker::Host::RebootFailure, /Boot time did not reset/)
289
- end
359
+ expect { instance.reboot }.to raise_error(Beaker::Host::RebootFailure, /Boot time did not reset/)
360
+ end
290
361
 
291
- it 'raises RebootFailure if the number of retries is changed' do
292
- expect(instance).to receive(:sleep).with(sleep_time)
293
- # bypass shutdown command itself
294
- expect(instance).to receive( :exec ).with(:shutdown_command_stub, anything).and_return(response).once
295
- expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_initial_response).once
296
- # allow the second boot_time and the hash arguments in exec, repeated 10 times by default
297
- expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_success_response).exactly(10).times
362
+ it 'raises RebootFailure if the number of retries is changed' do
363
+ expect(instance).to receive(:sleep).with(sleep_time)
364
+ # bypass shutdown command itself
365
+ expect(instance).to receive( :exec ).with(:shutdown_command_stub, anything).and_return(response).once
366
+ expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_initial_response).once
367
+ expect(instance).to receive( :exec ).with(:boot_time_command_stub, anything).and_return(boot_time_success_response).once
298
368
 
299
- expect { instance.reboot(wait_time=sleep_time, max_connection_tries=9, boot_time_retries=10) }.to raise_error(Beaker::Host::RebootFailure, /Boot time did not reset/)
369
+ expect { instance.reboot(wait_time=sleep_time, max_connection_tries=9, boot_time_retries=10) }.to raise_error(Beaker::Host::RebootFailure, /Boot time did not reset/)
370
+ end
371
+ end
372
+ end
300
373
  end
301
374
  end
302
-
303
375
  end
304
376
 
305
377
  describe '#enable_remote_rsyslog' do
@@ -314,30 +386,86 @@ module Beaker
314
386
  end
315
387
 
316
388
  describe '#which' do
317
- before do
318
- allow(instance).to receive(:execute)
319
- .with(where_command, :accept_all_exit_codes => true).and_return(result)
389
+ context 'when type -P works' do
390
+ before do
391
+ expect(instance).to receive(:execute)
392
+ .with('type -P true', :accept_all_exit_codes => true).and_return('/bin/true').once
393
+
394
+ allow(instance).to receive(:execute)
395
+ .with(where_command, :accept_all_exit_codes => true).and_return(result)
396
+ end
397
+
398
+ context 'when only the environment variable PATH is used' do
399
+ let(:where_command) { "type -P ruby" }
400
+ let(:result) { "/usr/bin/ruby.exe" }
401
+
402
+ it 'returns the correct path' do
403
+ response = instance.which('ruby')
404
+
405
+ expect(response).to eq(result)
406
+ end
407
+ end
408
+
409
+ context 'when command is not found' do
410
+ let(:where_command) { "type -P unknown" }
411
+ let(:result) { '' }
412
+
413
+ it 'return empty string if command is not found' do
414
+ response = instance.which('unknown')
415
+
416
+ expect(response).to eq(result)
417
+ end
418
+ end
320
419
  end
321
420
 
322
- context 'when only the environment variable PATH is used' do
323
- let(:where_command) { "which ruby" }
324
- let(:result) { "/usr/bin/ruby.exe" }
421
+ context 'when which works' do
422
+ before do
423
+ expect(instance).to receive(:execute)
424
+ .with('type -P true', :accept_all_exit_codes => true).and_return('').once
325
425
 
326
- it 'returns the correct path' do
327
- response = instance.which('ruby')
426
+ expect(instance).to receive(:execute)
427
+ .with('which true', :accept_all_exit_codes => true).and_return('/bin/true').once
328
428
 
329
- expect(response).to eq(result)
429
+ allow(instance).to receive(:execute)
430
+ .with(where_command, :accept_all_exit_codes => true).and_return(result)
431
+ end
432
+
433
+ context 'when only the environment variable PATH is used' do
434
+ let(:where_command) { "which ruby" }
435
+ let(:result) { "/usr/bin/ruby.exe" }
436
+
437
+ it 'returns the correct path' do
438
+ response = instance.which('ruby')
439
+
440
+ expect(response).to eq(result)
441
+ end
442
+ end
443
+
444
+ context 'when command is not found' do
445
+ let(:where_command) { "which unknown" }
446
+ let(:result) { '' }
447
+
448
+ it 'return empty string if command is not found' do
449
+ response = instance.which('unknown')
450
+
451
+ expect(response).to eq(result)
452
+ end
330
453
  end
331
454
  end
332
455
 
333
- context 'when command is not found' do
334
- let(:where_command) { "which unknown" }
335
- let(:result) { '' }
456
+ context 'when neither works' do
457
+ before do
458
+ expect(instance).to receive(:execute)
459
+ .with('type -P true', :accept_all_exit_codes => true).and_return('').once
336
460
 
337
- it 'return empty string if command is not found' do
338
- response = instance.which('unknown')
461
+ expect(instance).to receive(:execute)
462
+ .with('which true', :accept_all_exit_codes => true).and_return('').once
463
+ end
339
464
 
340
- expect(response).to eq(result)
465
+ context 'when only the environment variable PATH is used' do
466
+ it 'fails correctly' do
467
+ expect{instance.which('ruby')}.to raise_error(/suitable/)
468
+ end
341
469
  end
342
470
  end
343
471
  end