bashcov 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6613eed0d116984da22b7fb51ddd45617e148928
4
+ data.tar.gz: 289ef645df22d964dbe8275837458fe5e044d110
5
+ SHA512:
6
+ metadata.gz: 6e461f96cde82d60a97f7458cdf40cfcaac55621c4cf0c0c028ac859880f1d3c3b569b5270331ef7754da2d9cfe77bea3ec892c5e80df27ebeb72a432ab6be3d
7
+ data.tar.gz: 5c4af2c0ad3e0c51e6d7cb5b4ca5288326781b6ef068d22b63ec32abe4cf1898ab518c7bd16dc2ee1709d9f16e1e1dcef3e0b699259dca31478d33771d459893
data/.travis.yml CHANGED
@@ -10,3 +10,4 @@ rvm:
10
10
  matrix:
11
11
  allow_failures:
12
12
  - rvm: ruby-head
13
+ - rvm: rbx-19mode
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Bashcov [![Build Status](https://secure.travis-ci.org/infertux/bashcov.png?branch=master)](https://travis-ci.org/infertux/bashcov) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/infertux/bashcov)
1
+ # Bashcov [![Build Status](https://secure.travis-ci.org/infertux/bashcov.png?branch=master)](https://travis-ci.org/infertux/bashcov) [![Code Climate](https://codeclimate.com/github/infertux/bashcov.png)](https://codeclimate.com/github/infertux/bashcov)
2
2
 
3
3
  [bashcov] is [simplecov] for Bash.
4
4
 
@@ -37,10 +37,6 @@ After a bit of parsing, it sends results through _simplecov_ which generates an
37
37
 
38
38
  And of course, you can take the most of _simplecov_ by adding a `.simplecov` file in your project's root (like [this](https://github.com/infertux/bashcov/blob/master/spec/test_app/.simplecov)).
39
39
 
40
- ## Todo
41
-
42
- - semver
43
-
44
40
  ## License
45
41
 
46
42
  MIT
data/bashcov.gemspec CHANGED
@@ -19,7 +19,6 @@ Gem::Specification.new do |gem|
19
19
  gem.require_paths = ["lib"]
20
20
 
21
21
  gem.add_dependency 'simplecov'
22
- gem.add_dependency 'open4'
23
22
 
24
23
  gem.add_development_dependency 'rake'
25
24
  gem.add_development_dependency 'rspec'
data/lib/bashcov.rb CHANGED
@@ -26,6 +26,42 @@ module Bashcov
26
26
  # @raise [SystemExit] if invalid arguments are given
27
27
  # @return [void]
28
28
  def parse_options! args
29
+ option_parser.parse!(args)
30
+
31
+ if args.empty?
32
+ abort("You must give exactly one command to execute.")
33
+ else
34
+ @options.command = args.join(' ')
35
+ end
36
+ end
37
+
38
+ # @return [String] The project's root directory
39
+ def root_directory
40
+ Dir.getwd
41
+ end
42
+
43
+ # Program name including version for easy consistent output
44
+ # @return [String]
45
+ def name
46
+ "bashcov v#{VERSION}"
47
+ end
48
+
49
+ # Helper to get a pre-filled coverage array for a given file
50
+ # @todo This is generic and should be moved in some helpers file.
51
+ # @api private
52
+ # @param [String] filename The file to cover.
53
+ # @param [nil, Integer] fill Value to fill the array with.
54
+ # @return [Array] An array of the size of the given file.
55
+ # @example
56
+ # coverage_array('file.rb') #=> [0, 0, 0] # assuming file.rb has 3 lines
57
+ def coverage_array(filename, fill = Line::UNCOVERED)
58
+ lines = File.readlines(filename).size
59
+ [fill] * lines
60
+ end
61
+
62
+ private
63
+
64
+ def option_parser
29
65
  OptionParser.new do |opts|
30
66
  opts.program_name = 'bashcov'
31
67
  opts.version = Bashcov::VERSION
@@ -58,39 +94,8 @@ module Bashcov
58
94
  puts opts.ver
59
95
  exit
60
96
  end
61
-
62
- end.parse!(args)
63
-
64
- if args.empty?
65
- abort("You must give exactly one command to execute.")
66
- else
67
- @options.command = args.join(' ')
68
97
  end
69
98
  end
70
-
71
- # @return [String] The project's root directory
72
- def root_directory
73
- Dir.getwd
74
- end
75
-
76
- # Program name including version for easy consistent output
77
- # @return [String]
78
- def name
79
- "bashcov v#{VERSION}"
80
- end
81
-
82
- # Helper to get a pre-filled coverage array for a given file
83
- # @todo This is generic and should be moved in some helpers file.
84
- # @api private
85
- # @param [String] filename The file to cover.
86
- # @param [nil, Integer] fill Value to fill the array with.
87
- # @return [Array] An array of the size of the given file.
88
- # @example
89
- # coverage_array('file.rb') #=> [0, 0, 0] # assuming file.rb has 3 lines
90
- def coverage_array(filename, fill = Line::UNCOVERED)
91
- lines = File.readlines(filename).size
92
- [fill] * lines
93
- end
94
99
  end
95
100
  end
96
101
 
data/lib/bashcov/lexer.rb CHANGED
@@ -28,6 +28,7 @@ module Bashcov
28
28
 
29
29
  line.empty? or
30
30
  start_with.any? { |token| line.start_with? token } or
31
+ end_with.any? { |token| line.end_with? token } or
31
32
  is.any? { |keyword| line == keyword } or
32
33
  line =~ /\A\w+\(\) {/ # function declared like this: "foo() {"
33
34
  end
@@ -41,5 +42,10 @@ module Bashcov
41
42
  def start_with
42
43
  %w(# function)
43
44
  end
45
+
46
+ # Lines ending with one of these tokens are irrelevant for coverage
47
+ def end_with
48
+ %w(\()
49
+ end
44
50
  end
45
51
  end
@@ -1,47 +1,27 @@
1
- require 'open4'
2
-
3
1
  module Bashcov
4
- # Runs a given command capturing output then computes code coverage.
2
+ # Runs a given command with xtrace enabled then computes code coverage.
5
3
  class Runner
6
- # @return [Array] +stdout+ from the last run
7
- attr_reader :stdout
8
-
9
- # @return [Array] +stderr+ from the last run
10
- attr_reader :stderr
11
-
12
4
  # @param [String] command Command to run
13
5
  def initialize command
14
6
  @command = command
15
7
  end
16
8
 
17
- # Runs the command capturing +stdout+ and +stderr+.
9
+ # Runs the command with appropriate xtrace settings.
18
10
  # @note Binds Bashcov +stdin+ to the program executed.
19
- # @note Uses two threads to stream +stdout+ and +stderr+ output in
20
- # realtime.
21
- # @return [void]
11
+ # @return [Process::Status] Status of the executed command
22
12
  def run
23
- setup
13
+ inject_xtrace_flag!
24
14
 
25
- Open4::popen4(@command) do |pid, stdin, stdout, stderr|
26
- stdin = $stdin # bind stdin
15
+ @xtrace = Xtrace.new
16
+ fd = @xtrace.file_descriptor
17
+ @command = "BASH_XTRACEFD=#{fd} PS4='#{Xtrace.ps4}' #{@command}"
18
+ options = {:in => :in, fd => fd} # bind fds to the child process
19
+ options.merge!({out: '/dev/null', err: '/dev/null'}) if Bashcov.options.mute
27
20
 
28
- [
29
- Thread.new { # stdout
30
- stdout.each do |line|
31
- @stdout << line
32
- $stdout.puts line unless Bashcov.options.mute
33
- end
34
- },
35
- Thread.new { # stderr
36
- stderr.each do |line|
37
- @stderr << line
38
- next if Bashcov.options.mute
39
- xtrace = Xtrace.new [line]
40
- $stderr.puts line if xtrace.xtrace_output.empty?
41
- end
42
- }
43
- ].map(&:join)
44
- end
21
+ pid = Process.spawn @command, options
22
+ Process.wait pid
23
+
24
+ $?
45
25
  end
46
26
 
47
27
  # @return [Hash] Coverage hash of the last run
@@ -72,9 +52,7 @@ module Bashcov
72
52
  # @return [Hash] Given hash including coverage result from {Xtrace}
73
53
  # @see Xtrace
74
54
  def add_coverage_result files
75
- xtraced_files = Xtrace.new(@stderr).files
76
-
77
- xtraced_files.each do |file, lines|
55
+ @xtrace.files.each do |file, lines|
78
56
  lines.each_with_index do |line, lineno|
79
57
  files[file] ||= Bashcov.coverage_array(file)
80
58
  files[file][lineno] = line if line
@@ -98,16 +76,7 @@ module Bashcov
98
76
 
99
77
  private
100
78
 
101
- def setup
102
- inject_xtrace_flag
103
-
104
- @stdout = []
105
- @stderr = []
106
-
107
- @command = "PS4='#{Xtrace.ps4}' #{@command}"
108
- end
109
-
110
- def inject_xtrace_flag
79
+ def inject_xtrace_flag!
111
80
  # SHELLOPTS must be exported so we use Ruby's ENV variable
112
81
  existing_flags = (ENV['SHELLOPTS'] || '').split(':')
113
82
  ENV['SHELLOPTS'] = (existing_flags | ['xtrace']).join(':')
@@ -1,4 +1,4 @@
1
1
  module Bashcov
2
2
  # Bashcov version
3
- VERSION = "0.0.6"
3
+ VERSION = "0.0.7"
4
4
  end
@@ -1,19 +1,19 @@
1
+ require 'tempfile'
2
+
1
3
  module Bashcov
2
4
  # This class manages +xtrace+ output.
3
5
  #
4
6
  # @see Runner
5
7
  class Xtrace
6
- # @param [Array] output Array of output lines.
7
- # @raise [ArgumentError] if the given +output+ is not an array
8
- def initialize output
9
- raise ArgumentError, "#{output} must be an array" unless output.is_a? Array
10
- @lines = output
8
+ # Creates a temporary file for xtrace output
9
+ def initialize
10
+ @xtrace_file = Tempfile.new 'xtrace_output'
11
+ @xtrace_file.unlink # unlink on create so other programs cannot access it
11
12
  end
12
13
 
13
- # Filters out non-xtrace lines.
14
- # @return [Array] xtrace output
15
- def xtrace_output
16
- @lines.select { |line| line =~ Xtrace.line_regexp }
14
+ # @return [Fixnum] File descriptor of the output file
15
+ def file_descriptor
16
+ @xtrace_file.fileno
17
17
  end
18
18
 
19
19
  # Parses xtrace output and computes coverage
@@ -22,17 +22,17 @@ module Bashcov
22
22
  def files
23
23
  files = {}
24
24
 
25
- xtrace_output.each do |line|
26
- match = line.match(Xtrace.line_regexp)
25
+ @xtrace_file.rewind
26
+ @xtrace_file.read.each_line do |line|
27
+ match = line.match(self.class.line_regexp)
28
+ next if match.nil? # multiline instruction
29
+
27
30
  filename = File.expand_path(match[:filename], Bashcov.root_directory)
28
31
  next if File.directory? filename
29
32
  raise "#{filename} is not a file" unless File.file? filename
30
33
 
31
- lineno = match[:lineno].to_i
32
- lineno -= 1 if lineno > 0
33
-
34
+ lineno = match[:lineno].to_i - 1
34
35
  files[filename] ||= Bashcov.coverage_array(filename)
35
-
36
36
  files[filename][lineno] += 1
37
37
  end
38
38
 
@@ -46,7 +46,7 @@ module Bashcov
46
46
  # character in filenames on Unix and Windows.
47
47
 
48
48
  # http://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in
49
- %Q{#{prefix}$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$(basename "${BASH_SOURCE[0]}")/${LINENO} BASHCOV}
49
+ %Q{#{prefix}$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$(basename "${BASH_SOURCE[0]}")/${LINENO} BASHCOV: }
50
50
  end
51
51
 
52
52
  private
@@ -62,7 +62,7 @@ module Bashcov
62
62
  end
63
63
 
64
64
  def self.line_regexp
65
- /\A#{depth_character}+#{prefix[1..-1]}(?<filename>.+)\/(?<lineno>\d+) BASHCOV/
65
+ /\A#{depth_character}+#{prefix[1..-1]}(?<filename>.+)\/(?<lineno>\d+) BASHCOV: /
66
66
  end
67
67
  end
68
68
  end
@@ -93,14 +93,14 @@ describe Bashcov::Runner do
93
93
  end
94
94
  end
95
95
 
96
- context "with options.mute = false" do
96
+ context "with options.mute = true" do
97
97
  before do
98
- Bashcov.options.mute = false
98
+ Bashcov.options.mute = true
99
99
  end
100
100
 
101
- it "does not print xtrace output" do
102
- $stderr.should_receive(:puts).at_least(:once) do |line|
103
- line.should_not match Bashcov::Xtrace.line_regexp
101
+ it "does not print the command output" do
102
+ [$stdout, $stderr].each do |io|
103
+ io.should_not_receive :write
104
104
  end
105
105
 
106
106
  runner.run
@@ -29,7 +29,7 @@ end
29
29
  def expected_coverage
30
30
  {
31
31
  "#{test_app}/never_called.sh" => [nil, nil, 0, nil],
32
- "#{test_app}/scripts/case.sh" => [nil, nil, nil, 2, 1, nil, 0, 0, 1, nil, nil, nil, 1, 1, nil],
32
+ "#{test_app}/scripts/case.sh" => [nil, nil, nil, 6, 1, nil, 0, 0, 1, nil, nil, nil, 1, 1, nil],
33
33
  "#{test_app}/scripts/function.sh" => [nil, nil, nil, 2, nil, nil, nil, 1, 1, nil, nil, 1, 1, nil],
34
34
  "#{test_app}/scripts/long_line.sh" => [nil, nil, 1, 1, 1, 0, nil],
35
35
  "#{test_app}/scripts/nested/simple.sh" => [nil, nil, nil, nil, 1, 1, nil, 0, nil, nil, 1, nil, nil],
@@ -37,10 +37,9 @@ def expected_coverage
37
37
  "#{test_app}/scripts/simple.sh" => [nil, nil, nil, nil, 1, 1, nil, 0, nil, nil, 1, nil, nil],
38
38
  "#{test_app}/scripts/source.sh" => [nil, nil, 1, nil, 2, nil],
39
39
  "#{test_app}/scripts/sourced.txt" => [nil, nil, 1, nil],
40
- "#{test_app}/scripts/stdin.sh" => [nil, nil, 1, 1, 1, nil],
41
- "#{test_app}/scripts/multiline.sh" => [nil, nil, 1, 2, 1, 1, 0, nil],
40
+ "#{test_app}/scripts/multiline.sh" => [nil, nil, 1, 2, 1, 1, 0, nil, nil, 0, 1, 2], # XXX the 3 last lines should be [1, 1, 1] - Bash bug
42
41
  "#{test_app}/scripts/executable" => [nil, nil, 1, nil],
43
- "#{test_app}/test_suite.sh" => [nil, nil, 2, nil, nil, 2, nil]
42
+ "#{test_app}/test_suite.sh" => [nil, nil, 2, nil, 1, nil]
44
43
  }
45
44
  end
46
45
 
@@ -6,3 +6,7 @@
6
6
  echo 'what?' || \
7
7
  echo 'no!'
8
8
 
9
+ variable=($(
10
+ echo hi
11
+ ))
12
+ echo after
@@ -2,6 +2,5 @@
2
2
 
3
3
  cd $(dirname $0)
4
4
 
5
- # `date` is sent on stdin for each file
6
- date | find scripts -type f -executable -exec '{}' \;
5
+ find scripts -type f -executable -exec '{}' \;
7
6
 
metadata CHANGED
@@ -1,142 +1,111 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bashcov
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
5
- prerelease:
4
+ version: 0.0.7
6
5
  platform: ruby
7
6
  authors:
8
7
  - Cédric Félizard
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-02-06 00:00:00.000000000 Z
11
+ date: 2013-03-05 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: simplecov
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: '0'
30
- - !ruby/object:Gem::Dependency
31
- name: open4
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
34
- requirements:
35
- - - ! '>='
36
- - !ruby/object:Gem::Version
37
- version: '0'
38
- type: :runtime
39
- prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ! '>='
24
+ - - '>='
44
25
  - !ruby/object:Gem::Version
45
26
  version: '0'
46
27
  - !ruby/object:Gem::Dependency
47
28
  name: rake
48
29
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
30
  requirements:
51
- - - ! '>='
31
+ - - '>='
52
32
  - !ruby/object:Gem::Version
53
33
  version: '0'
54
34
  type: :development
55
35
  prerelease: false
56
36
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
37
  requirements:
59
- - - ! '>='
38
+ - - '>='
60
39
  - !ruby/object:Gem::Version
61
40
  version: '0'
62
41
  - !ruby/object:Gem::Dependency
63
42
  name: rspec
64
43
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
44
  requirements:
67
- - - ! '>='
45
+ - - '>='
68
46
  - !ruby/object:Gem::Version
69
47
  version: '0'
70
48
  type: :development
71
49
  prerelease: false
72
50
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
51
  requirements:
75
- - - ! '>='
52
+ - - '>='
76
53
  - !ruby/object:Gem::Version
77
54
  version: '0'
78
55
  - !ruby/object:Gem::Dependency
79
56
  name: guard-rspec
80
57
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
58
  requirements:
83
- - - ! '>='
59
+ - - '>='
84
60
  - !ruby/object:Gem::Version
85
61
  version: '0'
86
62
  type: :development
87
63
  prerelease: false
88
64
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
65
  requirements:
91
- - - ! '>='
66
+ - - '>='
92
67
  - !ruby/object:Gem::Version
93
68
  version: '0'
94
69
  - !ruby/object:Gem::Dependency
95
70
  name: rb-inotify
96
71
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
72
  requirements:
99
- - - ! '>='
73
+ - - '>='
100
74
  - !ruby/object:Gem::Version
101
75
  version: '0'
102
76
  type: :development
103
77
  prerelease: false
104
78
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
79
  requirements:
107
- - - ! '>='
80
+ - - '>='
108
81
  - !ruby/object:Gem::Version
109
82
  version: '0'
110
83
  - !ruby/object:Gem::Dependency
111
84
  name: cane
112
85
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
86
  requirements:
115
- - - ! '>='
87
+ - - '>='
116
88
  - !ruby/object:Gem::Version
117
89
  version: '0'
118
90
  type: :development
119
91
  prerelease: false
120
92
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
93
  requirements:
123
- - - ! '>='
94
+ - - '>='
124
95
  - !ruby/object:Gem::Version
125
96
  version: '0'
126
97
  - !ruby/object:Gem::Dependency
127
98
  name: yard
128
99
  requirement: !ruby/object:Gem::Requirement
129
- none: false
130
100
  requirements:
131
- - - ! '>='
101
+ - - '>='
132
102
  - !ruby/object:Gem::Version
133
103
  version: '0'
134
104
  type: :development
135
105
  prerelease: false
136
106
  version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
107
  requirements:
139
- - - ! '>='
108
+ - - '>='
140
109
  - !ruby/object:Gem::Version
141
110
  version: '0'
142
111
  description: Code coverage tool for Bash
@@ -165,7 +134,6 @@ files:
165
134
  - lib/bashcov/xtrace.rb
166
135
  - spec/bashcov/lexer_spec.rb
167
136
  - spec/bashcov/runner_spec.rb
168
- - spec/bashcov/xtrace_spec.rb
169
137
  - spec/bashcov_spec.rb
170
138
  - spec/spec_helper.rb
171
139
  - spec/support/common.rb
@@ -184,37 +152,34 @@ files:
184
152
  - spec/test_app/scripts/simple.sh
185
153
  - spec/test_app/scripts/source.sh
186
154
  - spec/test_app/scripts/sourced.txt
187
- - spec/test_app/scripts/stdin.sh
188
155
  - spec/test_app/test_suite.sh
189
156
  homepage: https://github.com/infertux/bashcov
190
157
  licenses:
191
158
  - MIT
159
+ metadata: {}
192
160
  post_install_message:
193
161
  rdoc_options: []
194
162
  require_paths:
195
163
  - lib
196
164
  required_ruby_version: !ruby/object:Gem::Requirement
197
- none: false
198
165
  requirements:
199
- - - ! '>='
166
+ - - '>='
200
167
  - !ruby/object:Gem::Version
201
168
  version: '0'
202
169
  required_rubygems_version: !ruby/object:Gem::Requirement
203
- none: false
204
170
  requirements:
205
- - - ! '>='
171
+ - - '>='
206
172
  - !ruby/object:Gem::Version
207
173
  version: '0'
208
174
  requirements: []
209
175
  rubyforge_project:
210
- rubygems_version: 1.8.24
176
+ rubygems_version: 2.0.0
211
177
  signing_key:
212
- specification_version: 3
178
+ specification_version: 4
213
179
  summary: Code coverage tool for Bash
214
180
  test_files:
215
181
  - spec/bashcov/lexer_spec.rb
216
182
  - spec/bashcov/runner_spec.rb
217
- - spec/bashcov/xtrace_spec.rb
218
183
  - spec/bashcov_spec.rb
219
184
  - spec/spec_helper.rb
220
185
  - spec/support/common.rb
@@ -233,6 +198,5 @@ test_files:
233
198
  - spec/test_app/scripts/simple.sh
234
199
  - spec/test_app/scripts/source.sh
235
200
  - spec/test_app/scripts/sourced.txt
236
- - spec/test_app/scripts/stdin.sh
237
201
  - spec/test_app/test_suite.sh
238
202
  has_rdoc:
@@ -1,20 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Bashcov::Xtrace do
4
- let(:xtrace) {
5
- runner = Bashcov::Runner.new test_suite
6
- runner.run
7
- Bashcov::Xtrace.new runner.stderr
8
- }
9
-
10
- describe "#files" do
11
- let(:files) { xtrace.files }
12
- subject { files }
13
-
14
- it { should be_a Hash }
15
-
16
- it "contains expected files" do
17
- subject.keys.should =~ executed_files
18
- end
19
- end
20
- end
@@ -1,6 +0,0 @@
1
- #!/bin/bash
2
-
3
- echo "What's your input?"
4
- read
5
- echo "All right, you entered \`${REPLY}'."
6
-