shexecutor 0.0.20 → 0.0.21

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: abaf52298bab64d4d610fd898c8595bbbfe9b3a7
4
- data.tar.gz: 5d9cbd52b722d5fcca21de5756ab67214f3be3ca
3
+ metadata.gz: b48ef2c0244538d77d5a160f7eebe7e04f9b0873
4
+ data.tar.gz: 9271240df64b7fbe672eb5c767eeaad99652db6e
5
5
  SHA512:
6
- metadata.gz: e3c8314db1c8d18514d07d233c9e30d61b35412f662dea3b83607c3c4c3af3fdbd5a97dfbb874dbc7df4f9e4928b7cededa19b1ad1d46724547a650fb2abd603
7
- data.tar.gz: 384a910b71555021718514d492cf185057d23e0120ce40c9abacdaf790ad0a1d3a4f30a6e7b78cdd0ead4d49d4e28f600b89fa064001601d258e54573d7dbe90
6
+ metadata.gz: 4ee1b26893798c3442f4bbe2d6127fcb08e43cc8b802d03761635d23063a7a9bf4f98fbfc9d39d2852dba836cfa8cd564013b3935e0af1b8358c76f077371e45
7
+ data.tar.gz: 46eae96106d2f392485787b549d8c0469261de3890014d2c51c1c662ed0dbf82f4aede4c6f96a7a765972891f12c3fc95d4d5f9e83ad3412e2d565a14ca47b62
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ Gemfile.lock
1
2
  *swp
2
3
  coverage
3
4
  *gem
data/README.md CHANGED
@@ -161,12 +161,6 @@ end
161
161
 
162
162
  Please send feedback and comments to the author at:
163
163
 
164
- Ernst van Graan <ernst.van.graan@hetzner.co.za>
164
+ Ernst van Graan <ernstvangraan@gmail.com>
165
165
 
166
166
  Thanks to Sheldon Hearn for review and great ideas that unblocked complex challenges (https://rubygems.org/profiles/sheldonh).
167
-
168
- 1. Fork it ( https://github.com/[my-github-username]/executor/fork )
169
- 2. Create your feature branch (`git checkout -b my-new-feature`)
170
- 3. Commit your changes (`git commit -am 'Add some feature'`)
171
- 4. Push to the branch (`git push origin my-new-feature`)
172
- 5. Create a new Pull Request
@@ -1,3 +1,3 @@
1
1
  module SHExecutor
2
- VERSION = "0.0.20"
2
+ VERSION = "0.0.21"
3
3
  end
data/shexecutor.gemspec CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
7
7
  spec.name = "shexecutor"
8
8
  spec.version = SHExecutor::VERSION
9
9
  spec.authors = ["Ernst van Graan"]
10
- spec.email = ["ernst.van.graan@hetzner.co.za"]
10
+ spec.email = ["ernstvangraan@gmail.com"]
11
11
  spec.summary = %q{Execute shell commands easily and securely}
12
12
  spec.description = %q{Implements process replacement, forking, protection from shell injection, and a variety of output options}
13
13
  spec.homepage = ""
@@ -17,10 +17,11 @@ Gem::Specification.new do |spec|
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
+ spec.required_ruby_version = '>= 2.0'
20
21
 
21
- spec.add_development_dependency 'bundler'
22
- spec.add_development_dependency 'rake'
23
- spec.add_development_dependency 'rspec'
22
+ spec.add_development_dependency 'bundler', "~> 1.12.5"
23
+ spec.add_development_dependency 'rake', "~> 11.2.2"
24
+ spec.add_development_dependency 'rspec', "~> 3.5.0"
24
25
  spec.add_development_dependency 'simplecov'
25
26
  spec.add_development_dependency 'simplecov-rcov'
26
27
  spec.add_development_dependency 'byebug'
@@ -3,12 +3,29 @@ require 'shexecutor.rb'
3
3
  require 'tempfile'
4
4
  require 'mocks/kernel.rb'
5
5
  require 'mocks/result.rb'
6
+ require 'fileutils'
7
+
8
+ def temp_file_path(seed)
9
+ file = Tempfile.new(seed)
10
+ path = file.path
11
+ file.close
12
+ FileUtils.touch(path)
13
+ File.chmod(0744, path)
14
+ path
15
+ end
16
+
17
+ def ignore_tempfile_bug_on_older_rubies(ex)
18
+ if ex.message == 'stream closed'
19
+ puts "INDETERMINATE RESULT: Tempfile bug on older versions of ruby. Test result unreliable, but not a failure per se. Subsequent runs should succeed"
20
+ else
21
+ fail
22
+ end
23
+ end
6
24
 
7
25
  describe 'Executor' do
8
- before :all do
9
- @executable_file = Tempfile.new("testingargumenterror")
10
- File.chmod(0744, @executable_file.path)
11
- `echo "ls" >> #{@executable_file.path}`
26
+ before :each do
27
+ @executable_file = temp_file_path("testingargumenterror")
28
+ `echo "ls" >> #{@executable_file}`
12
29
  end
13
30
 
14
31
  context 'when initialized with no options' do
@@ -61,17 +78,21 @@ describe 'Executor' do
61
78
  expect{
62
79
  iut.validate
63
80
  }.to raise_error(ArgumentError, "Application path not found")
64
- f = Tempfile.new("testingargumenterror")
65
- iut = SHExecutor::Executor.new({:application_path => f.path})
66
- expect{
81
+ path = temp_file_path("testingargumenterror")
82
+ iut = SHExecutor::Executor.new({:application_path => path})
83
+ error_received = false
84
+ begin
67
85
  iut.validate
68
- }.to raise_error(ArgumentError, "Application path not executable,Suspected injection vulnerability due to space in application_path or the object being marked as 'tainted' by Ruby. Turn off strict checking if you are sure by setting :protect_against_injection to false")
86
+ rescue => ex
87
+ error_received = (ex.class == ArgumentError) and (ex.message.include?("Suspected injection vulnerability due to space in application_path or the object being marked as 'tainted' by Ruby. Turn off strict checking if you are sure by setting :protect_against_injection to false"))
88
+ end
89
+ expect(error_received).to eq(true)
69
90
  end
70
91
  end
71
92
 
72
93
  context 'when initialized with valid options' do
73
94
  it 'validate should not raise an exception' do
74
- iut = SHExecutor::Executor.new({:application_path => @executable_file.path, :protect_against_injection => false})
95
+ iut = SHExecutor::Executor.new({:application_path => @executable_file, :protect_against_injection => false})
75
96
  iut.validate
76
97
  end
77
98
  end
@@ -209,74 +230,102 @@ describe 'Executor' do
209
230
 
210
231
  context 'when asked to execute and block' do
211
232
  it 'should raise a Timeout::Error if a timeout is specified and the process does not exit before' do
212
- test_command = "/bin/sleep"
213
- test_params = ["5"]
214
- iut = SHExecutor::Executor.new({:timeout => 1, :wait_for_completion => true, :application_path => test_command, :params => test_params})
215
- before = Time.now
216
- expect {
217
- iut.execute
218
- }.to raise_error(Timeout::Error, "execution expired")
219
- after = Time.now
220
- expect(after - before).to be < 2.1
233
+ begin
234
+ test_command = "/bin/sleep"
235
+ test_params = ["5"]
236
+ iut = SHExecutor::Executor.new({:timeout => 1, :wait_for_completion => true, :application_path => test_command, :params => test_params})
237
+ before = Time.now
238
+ expect {
239
+ iut.execute
240
+ }.to raise_error(Timeout::Error, "execution expired")
241
+ after = Time.now
242
+ expect(after - before).to be < 2.1
243
+ rescue IOError => ex
244
+ ignore_tempfile_bug_on_older_rubies(ex)
245
+ end
221
246
  end
222
247
 
223
248
  it 'should kill the subprocess when a TimeoutError is raised' do
224
- test_command = "/bin/sleep"
225
- test_params = ["2"]
226
- iut = SHExecutor::Executor.new({:timeout => 1, :wait_for_completion => true, :application_path => test_command, :params => test_params})
227
- expect(Process).to receive(:kill)
228
- expect {
229
- iut.execute
230
- }.to raise_error(Timeout::Error, "execution expired")
249
+ begin
250
+ test_command = "/bin/sleep"
251
+ test_params = ["2"]
252
+ iut = SHExecutor::Executor.new({:timeout => 1, :wait_for_completion => true, :application_path => test_command, :params => test_params})
253
+ expect(Process).to receive(:kill)
254
+ expect {
255
+ iut.execute
256
+ }.to raise_error(Timeout::Error, "execution expired")
257
+ rescue IOError => ex
258
+ ignore_tempfile_bug_on_older_rubies(ex)
259
+ end
231
260
  end
232
261
 
233
262
  it 'should call run_process with the command and parameters specified' do
234
- test_command = "/bin/ls"
235
- test_params = ["/tmp/"]
236
- iut = SHExecutor::Executor.new({:wait_for_completion => true, :application_path => test_command, :params => test_params})
237
- stdin = stdout = stderr = StringIO.new
238
- expect(iut).to receive(:run_process).with(test_command, *test_params).and_return([stdout, stderr, Result.new(true)])
239
- iut.execute
263
+ begin
264
+ test_command = "/bin/ls"
265
+ test_params = ["/tmp/"]
266
+ iut = SHExecutor::Executor.new({:wait_for_completion => true, :application_path => test_command, :params => test_params})
267
+ stdin = stdout = stderr = StringIO.new
268
+ expect(iut).to receive(:run_process).with(test_command, *test_params).and_return([stdout, stderr, Result.new(true)])
269
+ iut.execute
270
+ rescue IOError => ex
271
+ ignore_tempfile_bug_on_older_rubies(ex)
272
+ end
240
273
  end
241
274
 
242
275
  it 'should use run_process with the command' do
243
- test_command = "/bin/ls"
244
- iut = SHExecutor::Executor.new({:wait_for_completion => true, :application_path => test_command})
245
- stdin = stdout = stderr = StringIO.new
246
- expect(iut).to receive(:run_process).with(test_command).and_return([stdout, stderr, Result.new(true)])
247
- iut.execute
276
+ begin
277
+ test_command = "/bin/ls"
278
+ iut = SHExecutor::Executor.new({:wait_for_completion => true, :application_path => test_command})
279
+ stdin = stdout = stderr = StringIO.new
280
+ expect(iut).to receive(:run_process).with(test_command).and_return([stdout, stderr, Result.new(true)])
281
+ iut.execute
282
+ rescue IOError => ex
283
+ ignore_tempfile_bug_on_older_rubies(ex)
284
+ end
248
285
  end
249
286
 
250
287
  it 'should block until completion' do
251
- test_command = "/bin/sleep"
252
- test_params = ["2"]
253
- iut = SHExecutor::Executor.new({:wait_for_completion => true, :application_path => test_command, :params => test_params})
254
- before = Time.now
255
- iut.execute
256
- after = Time.now
257
- expect(after - before).to be > 2
288
+ begin
289
+ test_command = "/bin/sleep"
290
+ test_params = ["2"]
291
+ iut = SHExecutor::Executor.new({:wait_for_completion => true, :application_path => test_command, :params => test_params})
292
+ before = Time.now
293
+ iut.execute
294
+ after = Time.now
295
+ expect(after - before).to be > 2
296
+ rescue IOError => ex
297
+ ignore_tempfile_bug_on_older_rubies(ex)
298
+ end
258
299
  end
259
300
 
260
301
  it 'should block until completion and still have access to the ouput' do
261
- file = Tempfile.new("testingargumenterror")
262
- File.chmod(0744, file.path)
263
- `echo "sleep 2" >> #{file.path}`
264
- `echo "echo 'this did run'" >> #{file.path}`
265
- test_command = file.path
266
- iut = SHExecutor::Executor.new({:protect_against_injection => false, :wait_for_completion => true, :application_path => test_command})
267
- before = Time.now
268
- iut.execute
269
- iut.flush
270
- expect(iut.stdout).to eq("this did run\n")
271
- after = Time.now
272
- expect(after - before).to be > 2
302
+ begin
303
+ path = temp_file_path("testingargumenterror")
304
+ `echo "sleep 2" >> #{path}`
305
+ `echo "echo 'this did run'" >> #{path}`
306
+ sleep 1
307
+ iut = SHExecutor::Executor.new({:protect_against_injection => false, :wait_for_completion => true, :application_path => path})
308
+ before = Time.now
309
+ iut.execute
310
+ iut.flush
311
+ expect(iut.stdout).to eq("this did run\n")
312
+ after = Time.now
313
+ expect(after - before).to be > 2
314
+ rescue IOError => ex
315
+ ignore_tempfile_bug_on_older_rubies(ex)
316
+ end
273
317
  end
274
318
 
275
319
  it 'should validate' do
276
- iut = SHExecutor::Executor.new({:wait_for_completion => true})
277
- expect{
278
- iut.execute
279
- }.to raise_error(ArgumentError, "No application path provided")
320
+ begin
321
+ iut = SHExecutor::Executor.new({:wait_for_completion => true})
322
+ expect{
323
+ iut.execute
324
+ }.to raise_error(ArgumentError, "No application path provided")
325
+
326
+ rescue IOError => ex
327
+ ignore_tempfile_bug_on_older_rubies(ex)
328
+ end
280
329
  end
281
330
  end
282
331
 
@@ -311,9 +360,15 @@ describe 'Executor' do
311
360
 
312
361
  it 'should raise an exception if one of the file operations fails' do
313
362
  @stdout_test_path = "/tmp/thisdirectorydoesnotexistdshlgh58iyg89rlehg8y/gn.dfllgyls54gh57479gh"
314
- expect {
363
+ error_received = false
364
+ begin
315
365
  execute_stdout_test_command
316
- }.to raise_error(Errno::ENOENT, "No such file or directory - /tmp/thisdirectorydoesnotexistdshlgh58iyg89rlehg8y/gn.dfllgyls54gh57479gh")
366
+ rescue => ex
367
+ error_received = (ex.class == Errno::ENOENT) and
368
+ (ex.message.include?("No such file or directory")) and
369
+ (ex.message.include?("/tmp/thisdirectorydoesnotexistdshlgh58iyg89rlehg8y/gn.dfllgyls54gh57479gh"))
370
+ end
371
+ expect(error_received).to eq(true)
317
372
  end
318
373
  end
319
374
 
@@ -333,24 +388,34 @@ describe 'Executor' do
333
388
  end
334
389
 
335
390
  it 'should append stderr to the file specified, and create it if it does not exist' do
336
- expect(execute_stderr_test_command).to eq("ls: /tmp/thisfiledoesnotexistsatgup80wh0hgoefhgohuo4whg4whg4w5hg0: No such file or directory\n")
391
+ expect(execute_stderr_test_command.include?("/tmp/thisfiledoesnotexistsatgup80wh0hgoefhgohuo4whg4whg4w5hg0")).to eq(true)
392
+ expect(execute_stderr_test_command.include?("No such file or directory")).to eq(true)
337
393
  end
338
394
 
339
395
  it 'should append stderr to the file specified, if it exists' do
340
396
  `echo "line 1" >> #{@stderr_test_path}`
341
- expect(execute_stderr_test_command).to eq("line 1\nls: /tmp/thisfiledoesnotexistsatgup80wh0hgoefhgohuo4whg4whg4w5hg0: No such file or directory\n")
397
+ expect(execute_stderr_test_command.include?("line 1")).to eq(true)
398
+ expect(execute_stderr_test_command.include?("/tmp/thisfiledoesnotexistsatgup80wh0hgoefhgohuo4whg4whg4w5hg0")).to eq(true)
399
+ expect(execute_stderr_test_command.include?("No such file or directory")).to eq(true)
342
400
  end
343
401
 
344
402
  it 'should delete if exists and create the specified file, then write to it if append is not set' do
345
403
  `echo "line 1" >> #{@stderr_test_path}`
346
- expect(execute_stderr_test_command(false)).to eq("ls: /tmp/thisfiledoesnotexistsatgup80wh0hgoefhgohuo4whg4whg4w5hg0: No such file or directory\n")
404
+ expect(execute_stderr_test_command(false).include?("/tmp/thisfiledoesnotexistsatgup80wh0hgoefhgohuo4whg4whg4w5hg0")).to eq(true)
405
+ expect(execute_stderr_test_command(false).include?("No such file or directory")).to eq(true)
347
406
  end
348
407
 
349
408
  it 'should raise an exception if one of the file operations fails' do
350
409
  @stderr_test_path = "/tmp/thisdirectorydoesnotexistdshlgh58iyg89rlehg8y/gn.dfllgyls54gh57479gh"
351
- expect {
410
+ error_received = false
411
+ begin
352
412
  execute_stderr_test_command
353
- }.to raise_error(Errno::ENOENT, "No such file or directory - /tmp/thisdirectorydoesnotexistdshlgh58iyg89rlehg8y/gn.dfllgyls54gh57479gh")
413
+ rescue => ex
414
+ error_received = (ex.class == Errno::ENOENT) and
415
+ (ex.message.include?("No such file or directory")) and
416
+ (ex.message.include?("/tmp/thisdirectorydoesnotexistdshlgh58iyg89rlehg8y/gn.dfllgyls54gh57479gh"))
417
+ end
418
+ expect(error_received).to eq(true)
354
419
  end
355
420
  end
356
421
 
@@ -372,7 +437,8 @@ describe 'Executor' do
372
437
  iut.execute
373
438
  iut.flush
374
439
  expect(iut.stdout).to be_nil
375
- expect(iut.stderr).to eq("ls: /tmp/thisfiledoesnotexistsatgup80wh0hgoefhgohuo4whg4whg4w5hg0: No such file or directory\n")
440
+ expect(iut.stderr.include?("/tmp/thisfiledoesnotexistsatgup80wh0hgoefhgohuo4whg4whg4w5hg0")).to eq(true)
441
+ expect(iut.stderr.include?("No such file or directory")).to eq(true)
376
442
  end
377
443
  end
378
444
  end
metadata CHANGED
@@ -1,110 +1,109 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shexecutor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.20
4
+ version: 0.0.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ernst van Graan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-26 00:00:00.000000000 Z
11
+ date: 2016-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 1.12.5
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: 1.12.5
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: 11.2.2
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: 11.2.2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: 3.5.0
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: 3.5.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: simplecov
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: simplecov-rcov
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: byebug
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  description: Implements process replacement, forking, protection from shell injection,
98
98
  and a variety of output options
99
99
  email:
100
- - ernst.van.graan@hetzner.co.za
100
+ - ernstvangraan@gmail.com
101
101
  executables: []
102
102
  extensions: []
103
103
  extra_rdoc_files: []
104
104
  files:
105
- - .gitignore
105
+ - ".gitignore"
106
106
  - Gemfile
107
- - Gemfile.lock
108
107
  - LICENSE.txt
109
108
  - README.md
110
109
  - Rakefile
@@ -125,17 +124,17 @@ require_paths:
125
124
  - lib
126
125
  required_ruby_version: !ruby/object:Gem::Requirement
127
126
  requirements:
128
- - - '>='
127
+ - - ">="
129
128
  - !ruby/object:Gem::Version
130
- version: '0'
129
+ version: '2.0'
131
130
  required_rubygems_version: !ruby/object:Gem::Requirement
132
131
  requirements:
133
- - - '>='
132
+ - - ">="
134
133
  - !ruby/object:Gem::Version
135
134
  version: '0'
136
135
  requirements: []
137
136
  rubyforge_project:
138
- rubygems_version: 2.0.14
137
+ rubygems_version: 2.4.8
139
138
  signing_key:
140
139
  specification_version: 4
141
140
  summary: Execute shell commands easily and securely
@@ -144,3 +143,4 @@ test_files:
144
143
  - spec/mocks/kernel.rb
145
144
  - spec/mocks/result.rb
146
145
  - spec/spec_helper.rb
146
+ has_rdoc:
data/Gemfile.lock DELETED
@@ -1,47 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- shexecutor (0.0.19)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- byebug (4.0.5)
10
- columnize (= 0.9.0)
11
- columnize (0.9.0)
12
- diff-lcs (1.2.5)
13
- docile (1.1.5)
14
- json (1.8.2)
15
- rake (10.4.2)
16
- rspec (3.2.0)
17
- rspec-core (~> 3.2.0)
18
- rspec-expectations (~> 3.2.0)
19
- rspec-mocks (~> 3.2.0)
20
- rspec-core (3.2.3)
21
- rspec-support (~> 3.2.0)
22
- rspec-expectations (3.2.1)
23
- diff-lcs (>= 1.2.0, < 2.0)
24
- rspec-support (~> 3.2.0)
25
- rspec-mocks (3.2.1)
26
- diff-lcs (>= 1.2.0, < 2.0)
27
- rspec-support (~> 3.2.0)
28
- rspec-support (3.2.2)
29
- simplecov (0.10.0)
30
- docile (~> 1.1.0)
31
- json (~> 1.8)
32
- simplecov-html (~> 0.10.0)
33
- simplecov-html (0.10.0)
34
- simplecov-rcov (0.2.3)
35
- simplecov (>= 0.4.1)
36
-
37
- PLATFORMS
38
- ruby
39
-
40
- DEPENDENCIES
41
- bundler
42
- byebug
43
- rake
44
- rspec
45
- shexecutor!
46
- simplecov
47
- simplecov-rcov