slather 2.3.0 → 2.4.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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/CHANGELOG.md +26 -0
- data/README.md +2 -2
- data/lib/slather/coverage_service/coveralls.rb +35 -0
- data/lib/slather/coverage_service/html_output.rb +3 -4
- data/lib/slather/profdata_coverage_file.rb +74 -34
- data/lib/slather/project.rb +40 -16
- data/lib/slather/version.rb +1 -1
- data/slather.gemspec +1 -1
- data/spec/fixtures/fixtures.xcodeproj/project.pbxproj +113 -4
- data/spec/fixtures/fixtures.xcodeproj/xcshareddata/xcschemes/aggregateFixturesTests.xcscheme +109 -0
- data/spec/fixtures/fixtures.xcodeproj/xcshareddata/xcschemes/fixturesTestsSecond.xcscheme +99 -0
- data/spec/fixtures/fixtures/fixtures.m +1 -1
- data/spec/fixtures/fixturesTests/fixturesTestsSecond.m +21 -0
- data/spec/fixtures/fixturesTests/{peekaviewTests.m → peekaviewTests/360/237/222/243.m} +1 -1
- data/spec/fixtures/fixtures_html/fixtures.m.html +1 -1
- data/spec/fixtures/fixtures_html/index.html +1 -1
- data/spec/fixtures/fixtures_html/{peekaviewTests.m.html → peekaviewTests/360/237/222/243.m.html} +4 -4
- data/spec/fixtures/gutter.json +1 -1
- data/spec/slather/coverage_file_spec.rb +1 -1
- data/spec/slather/coverage_service/coveralls_spec.rb +39 -0
- data/spec/slather/coverage_service/html_output_spec.rb +24 -24
- data/spec/slather/coverage_service/simple_output_spec.rb +2 -2
- data/spec/slather/profdata_coverage_spec.rb +27 -14
- data/spec/slather/project_spec.rb +11 -1
- data/spec/spec_helper.rb +1 -1
- metadata +50 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0b3fb54ecb063ddb137572a81d78d071c3abe64c
|
4
|
+
data.tar.gz: 7f18e0dce826e19e5929eff17d02368e5d0b27cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47ae378522e002970dea520e193b5de1bed30ed69a259cc1ddc492a54b703a796295faba7535c5749dc5323e18a3f583b1674700ca893a3d6082b0cb2f73b1cd
|
7
|
+
data.tar.gz: b87f45afcafb2d8add2baff4b01eaa21e45ed1ae630c017aff8447b6c9703197019e531420e5507a7013acebec6f73059b4e2ab26feb3ad9e92024d9c23a8d15
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,32 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## v2.4.0
|
6
|
+
|
7
|
+
* Xcode 8.3 support.
|
8
|
+
[ksuther](https://github.com/ksuther)
|
9
|
+
[#291](https://github.com/SlatherOrg/slather/pull/291)
|
10
|
+
|
11
|
+
* Automatically ignore headers in Xcode platform SDKs.
|
12
|
+
[ksuther](https://github.com/ksuther)
|
13
|
+
[#286](https://github.com/SlatherOrg/slather/pull/286)
|
14
|
+
|
15
|
+
* Automatically handle schemes with multiple build or test targets
|
16
|
+
[serges147](https://github.com/serges147)
|
17
|
+
[#275](https://github.com/SlatherOrg/slather/pull/275)
|
18
|
+
|
19
|
+
* Added TeamCity as a CI service option
|
20
|
+
[joshrlesch](https://github.com/joshrlesch)
|
21
|
+
[#279](https://github.com/SlatherOrg/slather/pull/279)
|
22
|
+
|
23
|
+
* Handle UTF-8 characters correctly in HTML reports
|
24
|
+
[0xced](https://github.com/0xced)
|
25
|
+
[#259](https://github.com/SlatherOrg/slather/pull/259)
|
26
|
+
|
27
|
+
* Fix hanging `xcodebuild` invocation when getting derived data path.
|
28
|
+
[arthurtoper](https://github.com/arthurtoper)
|
29
|
+
[#238](https://github.com/SlatherOrg/slather/pull/238), [#197](https://github.com/SlatherOrg/slather/issues/197), [#212](https://github.com/SlatherOrg/slather/issues/212), [#234](https://github.com/SlatherOrg/slather/issues/234)
|
30
|
+
|
5
31
|
## v2.3.0
|
6
32
|
|
7
33
|
* Fixes broken fallback value of `input_format` inside `configure_input_format`
|
data/README.md
CHANGED
@@ -91,7 +91,7 @@ before_install: rvm use $RVM_RUBY_VERSION
|
|
91
91
|
install: bundle install --without=documentation --path ../travis_bundle_dir
|
92
92
|
after_success:
|
93
93
|
- slather
|
94
|
-
- bash <(curl -s https://codecov.io/bash) -f path/to/xml_report/cobertura.xml
|
94
|
+
- bash <(curl -s https://codecov.io/bash) -f path/to/xml_report/cobertura.xml -X coveragepy -X gcov -X xcode
|
95
95
|
```
|
96
96
|
|
97
97
|
```yml
|
@@ -100,7 +100,7 @@ after_success:
|
|
100
100
|
test:
|
101
101
|
post:
|
102
102
|
- bundle exec slather
|
103
|
-
- bash <(curl -s https://codecov.io/bash)
|
103
|
+
- bash <(curl -s https://codecov.io/bash) -f path/to/xml_report/cobertura.xml -X coveragepy -X gcov -X xcode
|
104
104
|
```
|
105
105
|
|
106
106
|
> Private repo? Add `-t :uuid-repo-token` to the codecov uploader. Read more about uploading report to Codecov [here](https://github.com/codecov/codecov-bash)
|
@@ -26,6 +26,11 @@ module Slather
|
|
26
26
|
end
|
27
27
|
private :circleci_pull_request
|
28
28
|
|
29
|
+
def teamcity_job_id
|
30
|
+
ENV['TC_BUILD_NUMBER']
|
31
|
+
end
|
32
|
+
private :teamcity_job_id
|
33
|
+
|
29
34
|
def jenkins_job_id
|
30
35
|
ENV['BUILD_ID']
|
31
36
|
end
|
@@ -41,6 +46,11 @@ module Slather
|
|
41
46
|
end
|
42
47
|
private :jenkins_branch_name
|
43
48
|
|
49
|
+
def teamcity_branch_name
|
50
|
+
ENV['GIT_BRANCH'] || `git ls-remote --heads origin | grep $(git rev-parse HEAD) | cut -d / -f 3-`.chomp
|
51
|
+
end
|
52
|
+
private :teamcity_branch_name
|
53
|
+
|
44
54
|
def buildkite_job_id
|
45
55
|
ENV['BUILDKITE_BUILD_NUMBER']
|
46
56
|
end
|
@@ -63,6 +73,19 @@ module Slather
|
|
63
73
|
end
|
64
74
|
private :jenkins_git_info
|
65
75
|
|
76
|
+
def teamcity_git_info
|
77
|
+
{
|
78
|
+
head: {
|
79
|
+
:id => (`git log --format=%H -n 1 HEAD`.chomp || ""),
|
80
|
+
:author_name => (`git log --format=%an -n 1 HEAD`.chomp || ""),
|
81
|
+
:author_email => (`git log --format=%ae -n 1 HEAD`.chomp || ""),
|
82
|
+
:message => (`git log --format=%s -n 1 HEAD`.chomp || "")
|
83
|
+
},
|
84
|
+
:branch => teamcity_branch_name
|
85
|
+
}
|
86
|
+
end
|
87
|
+
private :teamcity_git_info
|
88
|
+
|
66
89
|
def circleci_build_url
|
67
90
|
"https://circleci.com/gh/" + ENV['CIRCLE_PROJECT_USERNAME'] || "" + "/" + ENV['CIRCLE_PROJECT_REPONAME'] || "" + "/" + ENV['CIRCLE_BUILD_NUM'] || ""
|
68
91
|
end
|
@@ -171,6 +194,18 @@ module Slather
|
|
171
194
|
else
|
172
195
|
raise StandardError, "Environment variable `BUILDKITE_BUILD_NUMBER` not set. Is this running on a buildkite build?"
|
173
196
|
end
|
197
|
+
elsif ci_service == :teamcity
|
198
|
+
if teamcity_job_id
|
199
|
+
{
|
200
|
+
:service_job_id => teamcity_job_id,
|
201
|
+
:service_name => "teamcity",
|
202
|
+
:repo_token => coverage_access_token,
|
203
|
+
:source_files => coverage_files.map(&:as_json),
|
204
|
+
:git => teamcity_git_info
|
205
|
+
}.to_json
|
206
|
+
else
|
207
|
+
raise StandardError, "Environment variable `TC_BUILD_NUMBER` not set. Is this running on a teamcity build?"
|
208
|
+
end
|
174
209
|
else
|
175
210
|
raise StandardError, "No support for ci named #{ci_service}"
|
176
211
|
end
|
@@ -157,13 +157,12 @@ module Slather
|
|
157
157
|
|
158
158
|
cov.table(:class => "source_code") {
|
159
159
|
cleaned_gcov_lines.each do |line|
|
160
|
-
data = line.split(line_number_separator, 3)
|
161
160
|
|
162
|
-
line_number =
|
161
|
+
line_number = coverage_file.line_number_in_line(line)
|
163
162
|
next unless line_number > 0
|
164
163
|
|
165
|
-
|
166
|
-
line_data = [line_number,
|
164
|
+
line_source = line.split(line_number_separator, 3)[2]
|
165
|
+
line_data = [line_number, line_source, hits_for_coverage_line(coverage_file, line)]
|
167
166
|
classes = ["num", "src", "coverage"]
|
168
167
|
|
169
168
|
cov.tr(:class => class_for_coverage_line(coverage_file,line)) {
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'slather/coverage_info'
|
2
2
|
require 'slather/coveralls_coverage'
|
3
|
+
require 'digest/md5'
|
3
4
|
|
4
5
|
module Slather
|
5
6
|
class ProfdataCoverageFile
|
@@ -7,31 +8,50 @@ module Slather
|
|
7
8
|
include CoverageInfo
|
8
9
|
include CoverallsCoverage
|
9
10
|
|
10
|
-
attr_accessor :project, :source, :line_data
|
11
|
+
attr_accessor :project, :source, :line_numbers_first, :line_data
|
11
12
|
|
12
|
-
def initialize(project, source)
|
13
|
+
def initialize(project, source, line_numbers_first)
|
13
14
|
self.project = project
|
14
15
|
self.source = source
|
16
|
+
self.line_numbers_first = line_numbers_first
|
15
17
|
create_line_data
|
16
18
|
end
|
17
19
|
|
18
20
|
def create_line_data
|
19
21
|
all_lines = source_code_lines
|
20
22
|
line_data = Hash.new
|
21
|
-
all_lines.each { |line| line_data[line_number_in_line(line)] = line }
|
23
|
+
all_lines.each { |line| line_data[line_number_in_line(line, self.line_numbers_first)] = line }
|
22
24
|
self.line_data = line_data
|
23
25
|
end
|
24
26
|
private :create_line_data
|
25
27
|
|
26
28
|
def path_on_first_line?
|
27
29
|
path = self.source.split("\n")[0].sub ":", ""
|
28
|
-
!path.include?("
|
30
|
+
!path.include?("|//")
|
29
31
|
end
|
30
32
|
|
31
33
|
def source_file_pathname
|
32
34
|
@source_file_pathname ||= begin
|
33
|
-
|
34
|
-
|
35
|
+
if path_on_first_line?
|
36
|
+
path = self.source.split("\n")[0].sub ":", ""
|
37
|
+
path &&= Pathname(path)
|
38
|
+
else
|
39
|
+
# llvm-cov was run with just one matching source file
|
40
|
+
# It doesn't print the source path in this case, so we have to find it ourselves
|
41
|
+
# This is slow because we read every source file and compare it, but this should only happen if there aren't many source files
|
42
|
+
digest = Digest::MD5.digest(self.raw_source)
|
43
|
+
path = nil
|
44
|
+
|
45
|
+
project.find_source_files.each do |file|
|
46
|
+
file_digest = Digest::MD5.digest(File.read(file).strip)
|
47
|
+
|
48
|
+
if digest == file_digest
|
49
|
+
path = file
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
path
|
54
|
+
end
|
35
55
|
end
|
36
56
|
end
|
37
57
|
|
@@ -58,6 +78,12 @@ module Slather
|
|
58
78
|
@all_lines
|
59
79
|
end
|
60
80
|
|
81
|
+
def raw_source
|
82
|
+
self.source.lines.map do |line|
|
83
|
+
line.split('|').last
|
84
|
+
end.join
|
85
|
+
end
|
86
|
+
|
61
87
|
def cleaned_gcov_data
|
62
88
|
source_data
|
63
89
|
end
|
@@ -66,10 +92,17 @@ module Slather
|
|
66
92
|
self.source
|
67
93
|
end
|
68
94
|
|
69
|
-
def line_number_in_line(line)
|
70
|
-
|
71
|
-
|
72
|
-
|
95
|
+
def line_number_in_line(line, line_numbers_first = self.line_numbers_first)
|
96
|
+
if line_numbers_first
|
97
|
+
line =~ /^(\s*)(\d*)/
|
98
|
+
group = $2
|
99
|
+
else
|
100
|
+
line =~ /^(\s*)(\d*)\|(\s*)(\d+)\|/
|
101
|
+
group = $4
|
102
|
+
end
|
103
|
+
|
104
|
+
if group != nil
|
105
|
+
match = group.strip
|
73
106
|
case match
|
74
107
|
when /[0-9]+/
|
75
108
|
return match.to_i
|
@@ -91,28 +124,43 @@ module Slather
|
|
91
124
|
|
92
125
|
def line_coverage_data
|
93
126
|
source_code_lines.map do |line|
|
94
|
-
coverage_for_line(line)
|
127
|
+
coverage_for_line(line, self.line_numbers_first)
|
95
128
|
end
|
96
129
|
end
|
97
130
|
|
98
|
-
def coverage_for_line(line)
|
131
|
+
def coverage_for_line(line, line_numbers_first = self.line_numbers_first)
|
99
132
|
line = line.gsub(":", "|")
|
100
|
-
line =~ /^(\s*)(\d*)\|/
|
101
133
|
|
102
|
-
if
|
134
|
+
if line_numbers_first
|
135
|
+
line =~ /^(\s*)(\d*)\|(\s*)(\d+)\|/
|
136
|
+
group = $4
|
137
|
+
else
|
138
|
+
line =~ /^(\s*)(\d*)\|/
|
139
|
+
group = $2
|
140
|
+
end
|
141
|
+
|
142
|
+
if group == nil
|
103
143
|
# Check for thousands or millions (llvm-cov outputs hit counts as 25.3k or 3.8M)
|
104
|
-
|
144
|
+
if line_numbers_first
|
145
|
+
did_match = line =~ /^(\s*)(\d+)\|(\s*)(\d+\.\d+)(k|M)\|/
|
146
|
+
group = $4
|
147
|
+
units_group = $5
|
148
|
+
else
|
149
|
+
did_match = line =~ /^(\s*)(\d+\.\d+)(k|M)\|/
|
150
|
+
group = $2
|
151
|
+
units_group = $3
|
152
|
+
end
|
105
153
|
|
106
154
|
if did_match
|
107
|
-
count =
|
108
|
-
units =
|
155
|
+
count = group.strip
|
156
|
+
units = units_group == 'k' ? 1000 : 1000000
|
109
157
|
|
110
158
|
(count.to_f * units).to_i
|
111
159
|
else
|
112
160
|
return nil
|
113
161
|
end
|
114
162
|
else
|
115
|
-
match =
|
163
|
+
match = group.strip
|
116
164
|
case match
|
117
165
|
when /[0-9]+/
|
118
166
|
match.to_i
|
@@ -144,24 +192,16 @@ module Slather
|
|
144
192
|
private :supported_file_extensions
|
145
193
|
|
146
194
|
def ignored?
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
195
|
+
# This indicates a llvm-cov coverage warning (occurs if a passed in source file
|
196
|
+
# is not covered or with ccache in some cases).
|
197
|
+
ignore = source_file_pathname.to_s.end_with? "isn't covered."
|
198
|
+
|
199
|
+
if !ignore
|
200
|
+
# Ignore source files inside of platform SDKs
|
201
|
+
ignore = (/Xcode.*\.app\/Contents\/Developer\/Platforms/ =~ source_file_pathname.to_s) != nil
|
153
202
|
end
|
154
|
-
ignore ? ignore : super
|
155
|
-
end
|
156
203
|
|
157
|
-
|
158
|
-
["MacOSX.platform/Developer/Library/Frameworks/XCTest.framework/Headers/XCTestAssertionsImpl.h",
|
159
|
-
"MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/objc/objc.h",
|
160
|
-
"MacOSX.platform/Developer/Library/Frameworks/XCTest.framework/Headers/XCTestAssertions.h",
|
161
|
-
# This indicates a llvm-cov coverage warning (occurs if a passed in source file
|
162
|
-
# is not covered or with ccache in some cases).
|
163
|
-
"isn't covered."]
|
204
|
+
ignore ? ignore : super
|
164
205
|
end
|
165
|
-
private :platform_ignore_list
|
166
206
|
end
|
167
207
|
end
|
data/lib/slather/project.rb
CHANGED
@@ -52,7 +52,7 @@ module Slather
|
|
52
52
|
|
53
53
|
attr_accessor :build_directory, :ignore_list, :ci_service, :coverage_service, :coverage_access_token, :source_directory,
|
54
54
|
:output_directory, :xcodeproj, :show_html, :verbose_mode, :input_format, :scheme, :workspace, :binary_file, :binary_basename, :source_files,
|
55
|
-
:decimals
|
55
|
+
:decimals, :llvm_version
|
56
56
|
|
57
57
|
alias_method :setup_for_coverage, :slather_setup_for_coverage
|
58
58
|
|
@@ -84,7 +84,7 @@ module Slather
|
|
84
84
|
end
|
85
85
|
|
86
86
|
# redirect stderr to avoid xcodebuild errors being printed.
|
87
|
-
build_settings = `xcodebuild #{projectOrWorkspaceArgument} #{schemeArgument} -showBuildSettings #{buildAction} 2>&1`
|
87
|
+
build_settings = `xcodebuild #{projectOrWorkspaceArgument} #{schemeArgument} -showBuildSettings #{buildAction} CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO 2>&1`
|
88
88
|
|
89
89
|
if build_settings
|
90
90
|
derived_data_path = build_settings.match(/ OBJROOT = (.+)/)
|
@@ -126,13 +126,14 @@ module Slather
|
|
126
126
|
def profdata_coverage_files
|
127
127
|
coverage_files = []
|
128
128
|
source_files = find_source_files || []
|
129
|
+
line_numbers_first = Gem::Version.new(self.llvm_version) >= Gem::Version.new('8.1.0')
|
129
130
|
|
130
131
|
if self.binary_file
|
131
132
|
self.binary_file.each do |binary_path|
|
132
133
|
files = profdata_llvm_cov_output(binary_path, source_files).split("\n\n")
|
133
134
|
|
134
135
|
coverage_files.concat(files.map do |source|
|
135
|
-
coverage_file = coverage_file_class.new(self, source)
|
136
|
+
coverage_file = coverage_file_class.new(self, source, line_numbers_first)
|
136
137
|
# If a single source file is used, the resulting output does not contain the file name.
|
137
138
|
coverage_file.source_file_pathname = source_files.first if source_files.count == 1
|
138
139
|
!coverage_file.ignored? ? coverage_file : nil
|
@@ -208,7 +209,8 @@ module Slather
|
|
208
209
|
private :unsafe_profdata_llvm_cov_output
|
209
210
|
|
210
211
|
def profdata_llvm_cov_output(binary_path, source_files)
|
211
|
-
unsafe_profdata_llvm_cov_output(binary_path, source_files)
|
212
|
+
output = unsafe_profdata_llvm_cov_output(binary_path, source_files)
|
213
|
+
output.valid_encoding? ? output : output.encode!('UTF-8', 'binary', :invalid => :replace, undef: :replace)
|
212
214
|
end
|
213
215
|
private :profdata_llvm_cov_output
|
214
216
|
|
@@ -239,6 +241,8 @@ module Slather
|
|
239
241
|
configure_input_format
|
240
242
|
configure_binary_file
|
241
243
|
configure_decimals
|
244
|
+
|
245
|
+
self.llvm_version = `xcrun llvm-cov --version`.match(/Apple LLVM version ([\d\.]+)/).captures[0]
|
242
246
|
rescue => e
|
243
247
|
puts e.message
|
244
248
|
puts failure_help_string
|
@@ -391,20 +395,9 @@ module Slather
|
|
391
395
|
|
392
396
|
xcscheme = Xcodeproj::XCScheme.new(xcscheme_path)
|
393
397
|
|
394
|
-
begin
|
395
|
-
buildable_name = xcscheme.build_action.entries[0].buildable_references[0].buildable_name
|
396
|
-
rescue
|
397
|
-
# xcodeproj will raise an exception if there are no entries in the build action
|
398
|
-
end
|
399
|
-
|
400
|
-
if buildable_name == nil or buildable_name.end_with? ".a"
|
401
|
-
# Can't run code coverage on static libraries, look for an associated test bundle
|
402
|
-
buildable_name = xcscheme.test_action.testables[0].buildable_references[0].buildable_name
|
403
|
-
end
|
404
|
-
|
405
398
|
configuration = xcscheme.test_action.build_configuration
|
406
399
|
|
407
|
-
search_list = binary_basename ||
|
400
|
+
search_list = binary_basename || find_buildable_names(xcscheme)
|
408
401
|
|
409
402
|
search_list.each do |search_for|
|
410
403
|
found_product = Dir["#{profdata_coverage_dir}/Products/#{configuration}*/#{search_for}*"].sort { |x, y|
|
@@ -461,6 +454,37 @@ module Slather
|
|
461
454
|
found_binaries.map { |binary| File.expand_path(binary) }
|
462
455
|
end
|
463
456
|
|
457
|
+
def find_buildable_names(xcscheme)
|
458
|
+
found_buildable_names = []
|
459
|
+
|
460
|
+
# enumerate build action entries
|
461
|
+
begin
|
462
|
+
xcscheme.build_action.entries.each do |entry|
|
463
|
+
buildable_name = entry.buildable_references[0].buildable_name
|
464
|
+
|
465
|
+
if !buildable_name.end_with? ".a"
|
466
|
+
# Can't run code coverage on static libraries
|
467
|
+
found_buildable_names.push(buildable_name)
|
468
|
+
end
|
469
|
+
end
|
470
|
+
rescue
|
471
|
+
# xcodeproj will raise an exception if there are no entries in the build action
|
472
|
+
end
|
473
|
+
|
474
|
+
# enumerate test action entries
|
475
|
+
begin
|
476
|
+
xcscheme.test_action.testables.each do |entry|
|
477
|
+
buildable_name = entry.buildable_references[0].buildable_name
|
478
|
+
found_buildable_names.push(buildable_name)
|
479
|
+
end
|
480
|
+
rescue
|
481
|
+
# just in case if there are no entries in the test action
|
482
|
+
end
|
483
|
+
|
484
|
+
# some items are both buildable and testable, so return only unique ones
|
485
|
+
found_buildable_names.uniq
|
486
|
+
end
|
487
|
+
|
464
488
|
def find_source_files
|
465
489
|
source_files = load_option_array("source_files")
|
466
490
|
return if source_files.nil?
|
data/lib/slather/version.rb
CHANGED