slather 2.4.4 → 2.4.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +5 -1
- data/.travis.yml +2 -12
- data/CHANGELOG.md +63 -1
- data/README.md +20 -0
- data/README_Images/test_scheme.png +0 -0
- data/assets/list.min.js +1 -1
- data/lib/slather.rb +1 -0
- data/lib/slather/command/coverage_command.rb +9 -0
- data/lib/slather/coverage_service/simple_output.rb +1 -0
- data/lib/slather/coverage_service/sonarqube_xml_output.rb +61 -0
- data/lib/slather/profdata_coverage_file.rb +24 -10
- data/lib/slather/project.rb +133 -44
- data/lib/slather/version.rb +1 -1
- data/slather.gemspec +14 -15
- data/spec/fixtures/sonarqube-generic-coverage.xml +93 -0
- data/spec/slather/cocoapods_plugin_spec.rb +1 -1
- data/spec/slather/coverage_service/coveralls_spec.rb +9 -0
- data/spec/slather/coverage_service/hardcover_spec.rb +9 -1
- data/spec/slather/coverage_service/simple_output_spec.rb +2 -0
- data/spec/slather/coverage_service/sonarqube_xml_spec.rb +46 -0
- data/spec/slather/profdata_coverage_spec.rb +21 -0
- data/spec/slather/project_spec.rb +126 -7
- data/spec/spec_helper.rb +1 -0
- metadata +50 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1e8bb7fa0d1346a2a81a47272a1f55d2625a8457d8c4b88a82f2b737792aa39a
|
4
|
+
data.tar.gz: a375044a21453e30695adf31c20f5a9ea885091d1eb3ac6fafc3f3ef9d44d752
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a9dddfd5dcf8160cd31327f170030f3520c2a885b7c56f6f2d7d470e5442b8c49c3f30ba289664767cc43d597415c2309654699a5ac2fd59db90ac5bc796697
|
7
|
+
data.tar.gz: 5f67d766eb09e18df9a2bf1016f49a3a7a7f912be2bf5e05ed31c925540fb51ccaef34e53f1dffaed6aadfef827a3e69aa1c7144fa30a024f9f72a1ce2d47605
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,20 +1,10 @@
|
|
1
1
|
language: objective-c
|
2
2
|
script: bundle exec rake
|
3
|
-
osx_image:
|
4
|
-
|
5
|
-
# Sets Travis to run the Ruby specs on OS X machines which are required to
|
6
|
-
# build the native extensions of Xcodeproj.
|
7
|
-
|
8
|
-
env:
|
9
|
-
- RVM_RUBY_VERSION=system
|
3
|
+
osx_image: xcode9.2
|
10
4
|
|
11
5
|
before_install:
|
12
6
|
- curl http://curl.haxx.se/ca/cacert.pem -o /usr/local/share/cacert.pem
|
13
|
-
-
|
14
|
-
- if [[ $RVM_RUBY_VERSION != 'system' ]]; then rvm install $RVM_RUBY_VERSION; fi
|
15
|
-
- rvm use $RVM_RUBY_VERSION
|
16
|
-
- if [[ $RVM_RUBY_VERSION == 'system' ]]; then export ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future; fi
|
17
|
-
- if [[ $RVM_RUBY_VERSION == 'system' ]]; then sudo gem install bundler --no-ri --no-rdoc; else gem install bundler --no-ri --no-rdoc; fi
|
7
|
+
- gem install bundler -v "~> 1.0" --no-ri --no-rdoc
|
18
8
|
|
19
9
|
install:
|
20
10
|
- bundle install --without=documentation
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,71 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## v2.4.9
|
4
|
+
|
5
|
+
* Added support for Sonarqube output
|
6
|
+
[adellibovi](https://github.com/adellibovi)
|
7
|
+
[#456](https://github.com/SlatherOrg/slather/pull/456)
|
8
|
+
|
9
|
+
## v2.4.8
|
10
|
+
|
11
|
+
* Optimize performance for many binaries
|
12
|
+
[cltnschlosser](https://github.com/cltnschlosser)
|
13
|
+
[#455](https://github.com/SlatherOrg/slather/pull/455)
|
14
|
+
|
15
|
+
* Don't generate line 0 in profdata_coverage_file.rb from line with error
|
16
|
+
[tthbalazs](https://github.com/tthbalazs)
|
17
|
+
[#449](https://github.com/SlatherOrg/slather/pull/449)
|
18
|
+
|
19
|
+
* coveralls dependency update
|
20
|
+
[GRiMe2D](https://github.com/GRiMe2D)
|
21
|
+
[#448](https://github.com/SlatherOrg/slather/pull/448)
|
22
|
+
|
23
|
+
## v2.4.7
|
24
|
+
|
25
|
+
* Update dependencies
|
26
|
+
[dnedrow](https://github.com/dnedrow)
|
27
|
+
|
28
|
+
* Fixed errors when llvm-cov argument length exceeds ARG_MAX
|
29
|
+
[weibel](https://github.com/weibel)
|
30
|
+
[#414](https://github.com/SlatherOrg/slather/pull/414)
|
31
|
+
|
32
|
+
* Show "No coverage directory found." instead of "implicit conversion nil into String"
|
33
|
+
[phimage](https://github.com/phimage)
|
34
|
+
[#381](https://github.com/SlatherOrg/slather/pull/381) [#341](https://github.com/SlatherOrg/slather/issues/341)
|
35
|
+
|
36
|
+
## v2.4.6
|
37
|
+
|
38
|
+
* Fix .dSYM and .swiftmodule files filtering in find_binary_files()
|
39
|
+
[krin-san](https://github.com/krin-san)
|
40
|
+
[#368](https://github.com/SlatherOrg/slather/pull/368)
|
41
|
+
|
42
|
+
* Fixed loading coverage for a single source file
|
43
|
+
[blackm00n](https://github.com/blackm00n)
|
44
|
+
[#377](https://github.com/SlatherOrg/slather/pull/377) [#398](https://github.com/SlatherOrg/slather/pull/398)
|
45
|
+
|
46
|
+
* Fixed truncated file list in HTML export
|
47
|
+
[miroslavkovac](https://github.com/miroslavkovac)
|
48
|
+
[#402](https://github.com/SlatherOrg/slather/pull/402) [#261](https://github.com/SlatherOrg/slather/issues/261)
|
49
|
+
|
50
|
+
## v2.4.5
|
51
|
+
|
52
|
+
* Support for specifying a specific binary architecture
|
53
|
+
[ksuther](https://github.com/ksuther), [nickolas-pohilets](https://github.com/nickolas-pohilets)
|
54
|
+
[#367](https://github.com/SlatherOrg/slather/pull/367)
|
55
|
+
|
56
|
+
* Added absolute statement count to simple output (instead of showing just a percentage)
|
57
|
+
[barrault01](https://github.com/barrault01), [ivanbrunel](https://github.com/ivanbruel)
|
58
|
+
[#365](https://github.com/SlatherOrg/slather/pull/365)
|
59
|
+
|
60
|
+
* Updated nokogiri dependency version
|
61
|
+
[#363](https://github.com/SlatherOrg/slather/issues/363), [#366](https://github.com/SlatherOrg/slather/pull/366)
|
62
|
+
|
63
|
+
* slather now requires ruby 2.1 or later (10.13 ships with 2.3.3)
|
64
|
+
|
3
65
|
## v2.4.4
|
4
66
|
|
5
67
|
* Added llvm-cov output format
|
6
|
-
[
|
68
|
+
[sgtsquiggs](https://github.com/sgtsquiggs) [#354](https://github.com/SlatherOrg/slather/pull/354)
|
7
69
|
|
8
70
|
* Exclude swiftmodule from product search
|
9
71
|
[lampietti](https://github.com/lampietti) [#352](https://github.com/SlatherOrg/slather/pull/352)
|
data/README.md
CHANGED
@@ -61,6 +61,26 @@ If you use a different configuration for your tests:
|
|
61
61
|
$ slather coverage -s --scheme YourXcodeSchemeName --configuration YourBuildConfigurationName path/to/project.xcodeproj
|
62
62
|
```
|
63
63
|
|
64
|
+
If your configuration produces a universal binary you need to specify a specific architecture to use:
|
65
|
+
|
66
|
+
```sh
|
67
|
+
$ slather coverage -s --arch x86_64 --scheme YourXcodeSchemeName --configuration YourBuildConfigurationName path/to/project.xcodeproj
|
68
|
+
```
|
69
|
+
|
70
|
+
### For multiple modules
|
71
|
+
|
72
|
+
If you want to run some modules, but not all (like modules created by CocoaPods) you can do it like this:
|
73
|
+
|
74
|
+
```sh
|
75
|
+
$ slather coverage --binary-basename module1 --binary-basename module2 path/to/project.xcodeproj
|
76
|
+
```
|
77
|
+
You can also add it to the `.slather.yml` file as an array:
|
78
|
+
```yml
|
79
|
+
binary_basename:
|
80
|
+
- module1
|
81
|
+
- module2
|
82
|
+
```
|
83
|
+
|
64
84
|
### Setup for Xcode 5 and 6
|
65
85
|
|
66
86
|
Run this command to enable the `Generate Test Coverage` and `Instrument Program Flow` flags for your project:
|
Binary file
|
data/assets/list.min.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
!function(){function a(b,c,d){var e=a.resolve(b);if(null==e){d=d||b,c=c||"root";var f=new Error('Failed to require "'+d+'" from "'+c+'"');throw f.path=d,f.parent=c,f.require=!0,f}var g=a.modules[e];if(!g._resolving&&!g.exports){var h={};h.exports={},h.client=h.component=!0,g._resolving=!0,g.call(this,h.exports,a.relative(e),h),delete g._resolving,g.exports=h.exports}return g.exports}a.modules={},a.aliases={},a.resolve=function(b){"/"===b.charAt(0)&&(b=b.slice(1));for(var c=[b,b+".js",b+".json",b+"/index.js",b+"/index.json"],d=0;d
|
1
|
+
var List=function(t){function e(n){if(r[n])return r[n].exports;var i=r[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,e),i.l=!0,i.exports}var r={};return e.m=t,e.c=r,e.i=function(t){return t},e.d=function(t,r,n){e.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:n})},e.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=11)}([function(t,e,r){function n(t){if(!t||!t.nodeType)throw new Error("A DOM element reference is required");this.el=t,this.list=t.classList}var i=r(4),s=/\s+/;Object.prototype.toString;t.exports=function(t){return new n(t)},n.prototype.add=function(t){if(this.list)return this.list.add(t),this;var e=this.array(),r=i(e,t);return~r||e.push(t),this.el.className=e.join(" "),this},n.prototype.remove=function(t){if(this.list)return this.list.remove(t),this;var e=this.array(),r=i(e,t);return~r&&e.splice(r,1),this.el.className=e.join(" "),this},n.prototype.toggle=function(t,e){return this.list?("undefined"!=typeof e?e!==this.list.toggle(t,e)&&this.list.toggle(t):this.list.toggle(t),this):("undefined"!=typeof e?e?this.add(t):this.remove(t):this.has(t)?this.remove(t):this.add(t),this)},n.prototype.array=function(){var t=this.el.getAttribute("class")||"",e=t.replace(/^\s+|\s+$/g,""),r=e.split(s);return""===r[0]&&r.shift(),r},n.prototype.has=n.prototype.contains=function(t){return this.list?this.list.contains(t):!!~i(this.array(),t)}},function(t,e,r){var n=window.addEventListener?"addEventListener":"attachEvent",i=window.removeEventListener?"removeEventListener":"detachEvent",s="addEventListener"!==n?"on":"",a=r(5);e.bind=function(t,e,r,i){t=a(t);for(var o=0;o
|
data/lib/slather.rb
CHANGED
@@ -12,6 +12,7 @@ require 'slather/coverage_service/simple_output'
|
|
12
12
|
require 'slather/coverage_service/html_output'
|
13
13
|
require 'slather/coverage_service/json_output'
|
14
14
|
require 'slather/coverage_service/llvm_cov_output'
|
15
|
+
require 'slather/coverage_service/sonarqube_xml_output'
|
15
16
|
require 'cfpropertylist'
|
16
17
|
|
17
18
|
module Slather
|
@@ -13,6 +13,7 @@ class CoverageCommand < Clamp::Command
|
|
13
13
|
option ["--simple-output", "-s"], :flag, "Output coverage results to the terminal"
|
14
14
|
option ["--gutter-json", "-g"], :flag, "Output coverage results as Gutter JSON format"
|
15
15
|
option ["--cobertura-xml", "-x"], :flag, "Output coverage results as Cobertura XML format"
|
16
|
+
option ["--sonarqube-xml", "-sq"], :flag, "Output coverage results as Cobertura XML format"
|
16
17
|
option ["--llvm-cov", "-r"], :flag, "Output coverage as llvm-cov format"
|
17
18
|
option ["--json"], :flag, "Output coverage results as simple JSON"
|
18
19
|
option ["--html"], :flag, "Output coverage results as static html pages"
|
@@ -30,6 +31,7 @@ class CoverageCommand < Clamp::Command
|
|
30
31
|
option ["--workspace"], "WORKSPACE", "The workspace that the project was built in"
|
31
32
|
option ["--binary-file"], "BINARY_FILE", "The binary file against the which the coverage will be run", :multivalued => true
|
32
33
|
option ["--binary-basename"], "BINARY_BASENAME", "Basename of the file against which the coverage will be run", :multivalued => true
|
34
|
+
option ["--arch"], "ARCH", "Architecture to use from universal binaries"
|
33
35
|
option ["--source-files"], "SOURCE_FILES", "A Dir.glob compatible pattern used to limit the lookup to specific source files. Ignored in gcov mode.", :multivalued => true
|
34
36
|
option ["--decimals"], "DECIMALS", "The amount of decimals to use for % coverage reporting"
|
35
37
|
|
@@ -49,6 +51,7 @@ class CoverageCommand < Clamp::Command
|
|
49
51
|
setup_workspace
|
50
52
|
setup_binary_file
|
51
53
|
setup_binary_basename
|
54
|
+
setup_arch
|
52
55
|
setup_source_files
|
53
56
|
setup_decimals
|
54
57
|
|
@@ -122,6 +125,8 @@ class CoverageCommand < Clamp::Command
|
|
122
125
|
project.show_html = show?
|
123
126
|
elsif json?
|
124
127
|
project.coverage_service = :json
|
128
|
+
elsif sonarqube_xml?
|
129
|
+
project.coverage_service = :sonarqube_xml
|
125
130
|
end
|
126
131
|
end
|
127
132
|
|
@@ -153,6 +158,10 @@ class CoverageCommand < Clamp::Command
|
|
153
158
|
project.binary_basename = binary_basename_list if !binary_basename_list.empty?
|
154
159
|
end
|
155
160
|
|
161
|
+
def setup_arch
|
162
|
+
project.arch = arch
|
163
|
+
end
|
164
|
+
|
156
165
|
def setup_source_files
|
157
166
|
project.source_files = source_files_list if !source_files_list.empty?
|
158
167
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module Slather
|
5
|
+
module CoverageService
|
6
|
+
module SonarqubeXmlOutput
|
7
|
+
|
8
|
+
def coverage_file_class
|
9
|
+
if input_format == "profdata"
|
10
|
+
Slather::ProfdataCoverageFile
|
11
|
+
else
|
12
|
+
Slather::CoverageFile
|
13
|
+
end
|
14
|
+
end
|
15
|
+
private :coverage_file_class
|
16
|
+
|
17
|
+
def post
|
18
|
+
cobertura_xml_report = create_xml_report(coverage_files)
|
19
|
+
store_report(cobertura_xml_report)
|
20
|
+
end
|
21
|
+
|
22
|
+
def store_report(report)
|
23
|
+
output_file = 'sonarqube-generic-coverage.xml'
|
24
|
+
if output_directory
|
25
|
+
FileUtils.mkdir_p(output_directory)
|
26
|
+
output_file = File.join(output_directory, output_file)
|
27
|
+
end
|
28
|
+
File.write(output_file, report.to_s)
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_xml_report(coverage_files)
|
32
|
+
create_empty_xml_report
|
33
|
+
coverage_node = @doc.root
|
34
|
+
coverage_node['version'] = "1"
|
35
|
+
|
36
|
+
coverage_files.each do |coverage_file|
|
37
|
+
file_node = Nokogiri::XML::Node.new "file", @doc
|
38
|
+
file_node.parent = coverage_node
|
39
|
+
file_node['path'] = coverage_file.source_file_pathname_relative_to_repo_root.to_s
|
40
|
+
coverage_file.all_lines.each do |line|
|
41
|
+
if coverage_file.coverage_for_line(line)
|
42
|
+
line_node = Nokogiri::XML::Node.new "lineToCover", @doc
|
43
|
+
line_node['lineNumber'] = coverage_file.line_number_in_line(line)
|
44
|
+
line_node['covered'] = coverage_file.coverage_for_line(line) == 0 ? "false" : "true"
|
45
|
+
line_node.parent = file_node
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
@doc.to_xml
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_empty_xml_report
|
53
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
54
|
+
xml.coverage
|
55
|
+
end
|
56
|
+
@doc = builder.doc
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -18,7 +18,6 @@ module Slather
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def create_line_data
|
21
|
-
all_lines = source_code_lines
|
22
21
|
line_data = Hash.new
|
23
22
|
all_lines.each { |line| line_data[line_number_in_line(line, self.line_numbers_first)] = line }
|
24
23
|
self.line_data = line_data
|
@@ -26,14 +25,20 @@ module Slather
|
|
26
25
|
private :create_line_data
|
27
26
|
|
28
27
|
def path_on_first_line?
|
29
|
-
|
30
|
-
!path.include?("|//")
|
28
|
+
!source.lstrip.start_with?("1|")
|
31
29
|
end
|
32
30
|
|
33
31
|
def source_file_pathname
|
34
32
|
@source_file_pathname ||= begin
|
35
33
|
if path_on_first_line?
|
36
|
-
|
34
|
+
end_index = self.source.index(/:?\n/)
|
35
|
+
if end_index != nil
|
36
|
+
end_index -= 1
|
37
|
+
path = self.source[0..end_index]
|
38
|
+
else
|
39
|
+
# Empty file, output just contains path
|
40
|
+
path = self.source.sub ":", ""
|
41
|
+
end
|
37
42
|
path &&= Pathname(path)
|
38
43
|
else
|
39
44
|
# llvm-cov was run with just one matching source file
|
@@ -64,7 +69,16 @@ module Slather
|
|
64
69
|
end
|
65
70
|
|
66
71
|
def source_code_lines
|
67
|
-
self.source.split("\n")[(path_on_first_line? ? 1 : 0)..-1]
|
72
|
+
lines = self.source.split("\n")[(path_on_first_line? ? 1 : 0)..-1]
|
73
|
+
ignore_error_lines(lines)
|
74
|
+
end
|
75
|
+
|
76
|
+
def ignore_error_lines(lines, line_numbers_first = self.line_numbers_first)
|
77
|
+
if line_numbers_first
|
78
|
+
lines.reject { |line| line.lstrip.start_with?('|', '--') }
|
79
|
+
else
|
80
|
+
lines
|
81
|
+
end
|
68
82
|
end
|
69
83
|
|
70
84
|
def source_data
|
@@ -72,10 +86,7 @@ module Slather
|
|
72
86
|
end
|
73
87
|
|
74
88
|
def all_lines
|
75
|
-
|
76
|
-
@all_lines = source_code_lines
|
77
|
-
end
|
78
|
-
@all_lines
|
89
|
+
@all_lines ||= source_code_lines
|
79
90
|
end
|
80
91
|
|
81
92
|
def raw_source
|
@@ -94,6 +105,9 @@ module Slather
|
|
94
105
|
|
95
106
|
def line_number_in_line(line, line_numbers_first = self.line_numbers_first)
|
96
107
|
if line_numbers_first
|
108
|
+
# Skip regex if the number is the first thing in the line
|
109
|
+
fastpath_number = line.to_i
|
110
|
+
return fastpath_number if fastpath_number != 0
|
97
111
|
line =~ /^(\s*)(\d*)/
|
98
112
|
group = $2
|
99
113
|
else
|
@@ -123,7 +137,7 @@ module Slather
|
|
123
137
|
end
|
124
138
|
|
125
139
|
def line_coverage_data
|
126
|
-
|
140
|
+
all_lines.map do |line|
|
127
141
|
coverage_for_line(line, self.line_numbers_first)
|
128
142
|
end
|
129
143
|
end
|
data/lib/slather/project.rb
CHANGED
@@ -44,7 +44,7 @@ module Slather
|
|
44
44
|
class Project < Xcodeproj::Project
|
45
45
|
|
46
46
|
attr_accessor :build_directory, :ignore_list, :ci_service, :coverage_service, :coverage_access_token, :source_directory,
|
47
|
-
:output_directory, :xcodeproj, :show_html, :verbose_mode, :input_format, :scheme, :workspace, :binary_file, :binary_basename, :source_files,
|
47
|
+
:output_directory, :xcodeproj, :show_html, :verbose_mode, :input_format, :scheme, :workspace, :binary_file, :binary_basename, :arch, :source_files,
|
48
48
|
:decimals, :llvm_version, :configuration
|
49
49
|
|
50
50
|
alias_method :setup_for_coverage, :slather_setup_for_coverage
|
@@ -118,24 +118,11 @@ module Slather
|
|
118
118
|
|
119
119
|
def profdata_coverage_files
|
120
120
|
coverage_files = []
|
121
|
-
source_files = find_source_files || []
|
122
|
-
line_numbers_first = Gem::Version.new(self.llvm_version) >= Gem::Version.new('8.1.0')
|
123
121
|
|
124
122
|
if self.binary_file
|
125
123
|
self.binary_file.each do |binary_path|
|
126
|
-
|
127
|
-
|
128
|
-
coverage_files.concat(files.map do |source|
|
129
|
-
coverage_file = coverage_file_class.new(self, source, line_numbers_first)
|
130
|
-
# If a single source file is used, the resulting output does not contain the file name.
|
131
|
-
coverage_file.source_file_pathname = source_files.first if source_files.count == 1
|
132
|
-
!coverage_file.ignored? ? coverage_file : nil
|
133
|
-
end.compact)
|
134
|
-
|
135
|
-
if !source_files.empty?
|
136
|
-
coverage_file_paths = coverage_files.map { |file| file.source_file_pathname }.to_set
|
137
|
-
source_files.select! { |path| !coverage_file_paths.include?(path) }
|
138
|
-
end
|
124
|
+
pathnames_per_binary = pathnames_per_binary(binary_path)
|
125
|
+
coverage_files.concat(create_coverage_files_for_binary(binary_path, pathnames_per_binary))
|
139
126
|
end
|
140
127
|
end
|
141
128
|
|
@@ -143,6 +130,55 @@ module Slather
|
|
143
130
|
end
|
144
131
|
private :profdata_coverage_files
|
145
132
|
|
133
|
+
def pathnames_per_binary(binary_path)
|
134
|
+
coverage_json_string = llvm_cov_export_output(binary_path)
|
135
|
+
coverage_json = JSON.parse(coverage_json_string)
|
136
|
+
coverage_json["data"].reduce([]) do |result, chunk|
|
137
|
+
result.concat(chunk["files"].map do |file|
|
138
|
+
Pathname(file["filename"]).realpath
|
139
|
+
end)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
private :pathnames_per_binary
|
143
|
+
|
144
|
+
def create_coverage_files_for_binary(binary_path, pathnames_per_binary)
|
145
|
+
coverage_files = []
|
146
|
+
|
147
|
+
begin
|
148
|
+
coverage_files.concat(create_coverage_files(binary_path, pathnames_per_binary))
|
149
|
+
rescue Errno::E2BIG => e
|
150
|
+
# pathnames_per_binary is too big for the OS to handle so it's split in two halfs which are processed independently
|
151
|
+
if pathnames_per_binary.count > 1
|
152
|
+
left, right = pathnames_per_binary.each_slice( (pathnames_per_binary.size/2.0).round ).to_a
|
153
|
+
coverage_files.concat(create_coverage_files_for_binary(binary_path, left))
|
154
|
+
coverage_files.concat(create_coverage_files_for_binary(binary_path, right))
|
155
|
+
else
|
156
|
+
# pathnames_per_binary contains one element which is too big for the OS to handle.
|
157
|
+
raise e, "#{e}. A path in your project is close to the E2BIG limit. https://github.com/SlatherOrg/slather/pull/414", e.backtrace
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
coverage_files
|
162
|
+
end
|
163
|
+
private :create_coverage_files_for_binary
|
164
|
+
|
165
|
+
def create_coverage_files(binary_path, pathnames)
|
166
|
+
line_numbers_first = Gem::Version.new(self.llvm_version) >= Gem::Version.new('8.1.0')
|
167
|
+
files = create_profdata(binary_path, pathnames)
|
168
|
+
files.map do |source|
|
169
|
+
coverage_file = coverage_file_class.new(self, source, line_numbers_first)
|
170
|
+
# If a single source file is used, the resulting output does not contain the file name.
|
171
|
+
coverage_file.source_file_pathname = pathnames.first if pathnames.count == 1
|
172
|
+
!coverage_file.ignored? ? coverage_file : nil
|
173
|
+
end.compact
|
174
|
+
end
|
175
|
+
private :create_coverage_files
|
176
|
+
|
177
|
+
def create_profdata(binary_path, pathnames)
|
178
|
+
profdata_llvm_cov_output(binary_path, pathnames).split("\n\n")
|
179
|
+
end
|
180
|
+
private :create_profdata
|
181
|
+
|
146
182
|
def remove_extension(path)
|
147
183
|
path.split(".")[0..-2].join(".")
|
148
184
|
end
|
@@ -155,36 +191,38 @@ module Slather
|
|
155
191
|
end
|
156
192
|
|
157
193
|
def profdata_coverage_dir
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
194
|
+
@profdata_coverage_dir ||= begin
|
195
|
+
raise StandardError, "The specified build directory (#{self.build_directory}) does not exist" unless File.exists?(self.build_directory)
|
196
|
+
dir = nil
|
197
|
+
if self.scheme
|
198
|
+
dir = Dir[File.join(build_directory,"/**/CodeCoverage/#{self.scheme}")].first
|
199
|
+
else
|
200
|
+
dir = Dir[File.join(build_directory,"/**/#{first_product_name}")].first
|
201
|
+
end
|
165
202
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
203
|
+
if dir == nil
|
204
|
+
# Xcode 7.3 moved the location of Coverage.profdata
|
205
|
+
dir = Dir[File.join(build_directory,"/**/CodeCoverage")].first
|
206
|
+
end
|
170
207
|
|
171
|
-
|
172
|
-
|
173
|
-
|
208
|
+
if dir == nil && Slather.xcode_version[0] >= 9
|
209
|
+
# Xcode 9 moved the location of Coverage.profdata
|
210
|
+
coverage_files = Dir[File.join(build_directory, "/**/ProfileData/*/Coverage.profdata")]
|
174
211
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
212
|
+
if coverage_files.count == 0
|
213
|
+
# Look up one directory
|
214
|
+
# The ProfileData directory is next to Intermediates.noindex (in previous versions of Xcode the coverage was inside Intermediates)
|
215
|
+
coverage_files = Dir[File.join(build_directory, "../**/ProfileData/*/Coverage.profdata")]
|
216
|
+
end
|
180
217
|
|
181
|
-
|
182
|
-
|
218
|
+
if coverage_files != nil && coverage_files.count != 0
|
219
|
+
dir = Pathname.new(coverage_files.first).parent()
|
220
|
+
end
|
183
221
|
end
|
184
|
-
end
|
185
222
|
|
186
|
-
|
187
|
-
|
223
|
+
raise StandardError, "No coverage directory found." unless dir != nil
|
224
|
+
dir
|
225
|
+
end
|
188
226
|
end
|
189
227
|
|
190
228
|
def profdata_file
|
@@ -201,6 +239,30 @@ module Slather
|
|
201
239
|
end
|
202
240
|
private :profdata_file
|
203
241
|
|
242
|
+
def unsafe_llvm_cov_export_output(binary_path)
|
243
|
+
profdata_file_arg = profdata_file
|
244
|
+
if profdata_file_arg == nil
|
245
|
+
raise StandardError, "No Coverage.profdata files found. Please make sure the \"Code Coverage\" checkbox is enabled in your scheme's Test action or the build_directory property is set."
|
246
|
+
end
|
247
|
+
|
248
|
+
if binary_path == nil
|
249
|
+
raise StandardError, "No binary file found."
|
250
|
+
end
|
251
|
+
|
252
|
+
llvm_cov_args = %W(export -instr-profile #{profdata_file_arg} #{binary_path})
|
253
|
+
if self.arch
|
254
|
+
llvm_cov_args << "--arch" << self.arch
|
255
|
+
end
|
256
|
+
`xcrun llvm-cov #{llvm_cov_args.shelljoin}`
|
257
|
+
end
|
258
|
+
private :unsafe_llvm_cov_export_output
|
259
|
+
|
260
|
+
def llvm_cov_export_output(binary_path)
|
261
|
+
output = unsafe_llvm_cov_export_output(binary_path)
|
262
|
+
output.valid_encoding? ? output : output.encode!('UTF-8', 'binary', :invalid => :replace, undef: :replace)
|
263
|
+
end
|
264
|
+
private :llvm_cov_export_output
|
265
|
+
|
204
266
|
def unsafe_profdata_llvm_cov_output(binary_path, source_files)
|
205
267
|
profdata_file_arg = profdata_file
|
206
268
|
if profdata_file_arg == nil
|
@@ -212,6 +274,9 @@ module Slather
|
|
212
274
|
end
|
213
275
|
|
214
276
|
llvm_cov_args = %W(show -instr-profile #{profdata_file_arg} #{binary_path})
|
277
|
+
if self.arch
|
278
|
+
llvm_cov_args << "--arch" << self.arch
|
279
|
+
end
|
215
280
|
`xcrun llvm-cov #{llvm_cov_args.shelljoin} #{source_files.shelljoin}`
|
216
281
|
end
|
217
282
|
private :unsafe_profdata_llvm_cov_output
|
@@ -248,6 +313,7 @@ module Slather
|
|
248
313
|
configure_source_directory
|
249
314
|
configure_output_directory
|
250
315
|
configure_input_format
|
316
|
+
configure_arch
|
251
317
|
configure_binary_file
|
252
318
|
configure_decimals
|
253
319
|
|
@@ -358,6 +424,8 @@ module Slather
|
|
358
424
|
extend(Slather::CoverageService::HtmlOutput)
|
359
425
|
when :json
|
360
426
|
extend(Slather::CoverageService::JsonOutput)
|
427
|
+
when :sonarqube_xml
|
428
|
+
extend(Slather::CoverageService::SonarqubeXmlOutput)
|
361
429
|
else
|
362
430
|
raise ArgumentError, "`#{coverage_service}` is not a valid coverage service. Try `terminal`, `coveralls`, `gutter_json`, `cobertura_xml` or `html`"
|
363
431
|
end
|
@@ -370,6 +438,10 @@ module Slather
|
|
370
438
|
end
|
371
439
|
end
|
372
440
|
|
441
|
+
def configure_arch
|
442
|
+
self.arch ||= self.class.yml["arch"] if self.class.yml["arch"]
|
443
|
+
end
|
444
|
+
|
373
445
|
def decimal_f decimal_arg
|
374
446
|
configure_decimals unless decimals
|
375
447
|
decimal = "%.#{decimals}f" % decimal_arg
|
@@ -435,10 +507,17 @@ module Slather
|
|
435
507
|
# Sort the matches without the file extension to ensure better matches when there are multiple candidates
|
436
508
|
# For example, if the binary_basename is Test then we want Test.app to be matched before Test Helper.app
|
437
509
|
File.basename(x, File.extname(x)) <=> File.basename(y, File.extname(y))
|
438
|
-
}.
|
439
|
-
path.end_with? ".dSYM"
|
440
|
-
path.end_with? ".swiftmodule"
|
441
|
-
|
510
|
+
}.find { |path|
|
511
|
+
next if path.end_with? ".dSYM"
|
512
|
+
next if path.end_with? ".swiftmodule"
|
513
|
+
|
514
|
+
if File.directory? path
|
515
|
+
path = find_binary_file_in_bundle(path)
|
516
|
+
next if path.nil?
|
517
|
+
end
|
518
|
+
|
519
|
+
matches_arch(path)
|
520
|
+
}
|
442
521
|
|
443
522
|
if found_product and File.directory? found_product
|
444
523
|
found_binary = find_binary_file_in_bundle(found_product)
|
@@ -517,6 +596,16 @@ module Slather
|
|
517
596
|
found_buildable_names.uniq
|
518
597
|
end
|
519
598
|
|
599
|
+
def matches_arch(binary_path)
|
600
|
+
if self.arch
|
601
|
+
lipo_output = `lipo -info "#{binary_path}"`
|
602
|
+
archs_in_binary = lipo_output.split(':').last.split(' ')
|
603
|
+
archs_in_binary.include? self.arch
|
604
|
+
else
|
605
|
+
true
|
606
|
+
end
|
607
|
+
end
|
608
|
+
|
520
609
|
def find_source_files
|
521
610
|
source_files = load_option_array("source_files")
|
522
611
|
return if source_files.nil?
|