slather 2.3.0 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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